Anexo
install.packages("faraway")
install.packages("leaps")
install.packages("MASS")
install.packages("PASWR")
install.packages("car")
install.packages("ggplot2")
install.packages("GGally")
install.packages("corrplot")
install.packages("scatterplot3d")
install.packages("lmtest")
install.packages("plotly")
install.packages("mixlm")
library(faraway)
library(leaps)
library(MASS)
library(PASWR)
library(car)
library(ggplot2)
library(GGally)
library(corrplot)
library(plotly)
library(scatterplot3d)
library(lmtest)
library(mixlm)
# 1) Introduccion
data(cheddar)
attach(cheddar)
# Variable Respuesta: taste
# Variables Predictoras: Acetic, H2S, Lactic
# Estudiamos el tipo de las variables que van a formar parte de los posibles modelos
sapply(cheddar, class) # todas las variables son numericas
head(cheddar)
# Comprobamos que no hay entradas vacias
any(is.na(cheddar))
# De haberlas habido, podriamos haber tomado las siguientes decisiones:
# - eliminar las observaciones con valores NA
# - eliminar variables si muchas de las entradas vacias aparecen en ella
# - emplear métodos para predecir que valores deberian apercer en dichas entradas
# Histogramas de todas las variables
ids <- names(cheddar)
layout(matrix(1:4, nrow = 1))
y_lab_string <- "Cantidad"
for (id in ids) {
hist(cheddar[, id], xlab = id, ylab = y_lab_string, main = paste("Histogram of ", id))
y_lab_string <- ""
}
# Graficas de las relaciones entre variables.
plot(cheddar)
# Graficas de dispersion entre la variable respuesta "taste" y las variables predictoras.
layout(matrix(1:3, nrow = 1))
plot(Acetic, taste,
main = "Relación entre Taste y Acetic",
xlab = "Acetic", ylab = "Taste",
pch = 19, frame = FALSE)
plot(H2S, taste,
main = "Relación entre Taste y H2S",
xlab = "H2S", ylab = "Taste",
pch = 19, frame = FALSE)
plot(Lactic, taste,
main = "Relación entre Taste y Lactic",
xlab = "Lactic", ylab = "Taste",
pch = 19, frame = FALSE)
layout(matrix(1:1, nrow = 1))
summary(cheddar)
# 2) Estudio y evaluacion del modelo completo
x <- model.matrix( ~ Acetic + H2S + Lactic, data = cheddar)
betahat <- solve(crossprod(x, x), crossprod(x, taste))
betahat <- c(betahat)
betahat
# Comprobamos el resultado con funciones ya implementadas
model.all <- lm(taste ~ ., data = cheddar)
summary(model.all)
model.all$coefficients
anova(model.all)
# Intervalos de confianza de las betas del modelo completo
confint(model.all)
# Observamos que 0 esta en el intervalo de confianza de beta_0 y beta_Acetic, planteamos dos tests
# con hipótesis nula beta_i = 0 y hipotesis alternativa beta_i != 0.
# Comenzamos con beta_Acetic pues el valor estimado es más cercano a 0 que el de beta_0
modnoAcetic <- lm(taste ~ H2S + Lactic, data=cheddar)
anova(modnoAcetic,model.all) # no solo el p-valor > 0.05 sino que de hecho p-valor ~ 1, aceptamos la hipotesis nula.
modnoInterceptor <- lm(taste ~ H2S + Lactic + 0, data=cheddar) # modelo reducido sin interceptor
anova(modnoInterceptor,model.all) # el p-valor es menor que 0.05, luego no es suficiente para rechazar la hipotesis nula
# Veamos los p-valores de las variables predictoras
summary(model.all)$coeff[,4]
# Observamso que el p-valor de Acetic es el mas elevado, este resultado junto con el contrate de hipotesis que hemos hecho
# podemos deducir que la variable Acetic no sera muy relevante para el estudio de los distintos modelos que estudiaremos.
# Correlaciones de las variables que intervienen en el modelo completo
cor(cheddar)
ggpairs(cheddar)
mat_cor <- cor(cheddar, method = "pearson")
corrplot(mat_cor, type = "upper", order = "hclust", tl.col = "black", tl.srt = 45)
# Por ultimo veamos si hay outliers en el modelo completo
Model.all<-fortify(model.all)
outlierTest(model.all) # no los hay
# Por el metodo de Bonferroni
alpha <- 0.05
BCV <- qt(1-alpha/(2*30),26) # el valor critico de Bonferroni t_{1-alpha/2n;n-p-1}, n=30,p=3
BCV
sum(abs(rstudent(model.all))>BCV) # el metodo no nos da ninguna observacion
sort(abs(rstandard(model.all)),decreasing = TRUE)[1:3] # estos valores estan relativamente lejanos de BCV
# Veamos si por influenceIndexPlot() hay alguna observacion que pueda ser relevante
influenceIndexPlot(model.all) # en la tercera grafica se ve que la observacion 15 tiene un comportamiento anormal
# Comprobemos si los supuestos de los modelos de regresion lineal mejoran al retirar esta observacion
# de nuestro dataset. De ser asi, aceptamos que pueda ser una observacion que pejudique a nuestro modelo.
model.all_15<- lm(taste ~ ., data = cheddar[-15,])
# Homocedasticidad
ncvTest(model.all)
ncvTest(model.all_15) # empeora
# Normalidad
shapiro.test(resid(model.all))
shapiro.test(resid(model.all_15))# mejora
# Autocorrelacion
durbinWatsonTest(model.all)
durbinWatsonTest(model.all_15)# mejora
# Linealidad
resettest(model.all, power=2:3, type="regressor", data=cheddar)
resettest(model.all_15, power=2:3, type="regressor", data=cheddar)# empeora
# En el computo global no parece que los p-valores de estos tests den a entender una mejoria general del modelo.
# Si bien es cierto, tampoco los empeora y dependiendo del criterio a seguir podriamos decidir si es relevante o no.
# Nosotros hemos decidido no considerar la observacion 15 como tal.
# 3) Seleccion del mejor modelo. Metodos por pasos y por criterios
# Separacion del dataset en conjuntos de entrenamiento y test (70-30%)
# Hemos considerado varias semillas para abarcar más modelos. Además, hemos intentado evitar
# en la medida de lo poible que se repitan muchos elementos en los distintos conjuntos de test seleccionados.
set.seed(1)
train.1 <- sample(c(TRUE, FALSE), size = nrow(cheddar), replace = TRUE, prob = c(0.7, 0.3))
test.1 <- (!train.1)
sum(test.1)
model.all1 <- lm(taste ~ ., data = cheddar[train.1,])
set.seed(1100)
train.2 <- sample(c(TRUE, FALSE), size = nrow(cheddar), replace = TRUE, prob = c(0.7, 0.3))
test.2 <- (!train.2)
sum(test.2)
sum(test.1==TRUE & test.2==TRUE)#solo 1 preseguimos
model.all2 <- lm(taste ~ ., data = cheddar[train.2,])
set.seed(5)
train.3 <- sample(c(TRUE, FALSE), size = nrow(cheddar), replace = TRUE, prob = c(0.7, 0.3))
test.3 <- (!train.3)
sum(test.3)
sum(test.1==TRUE & test.3==TRUE)
sum(test.2==TRUE & test.3==TRUE)
model.all3 <- lm(taste ~ ., data = cheddar[train.3,])
# i) BACKWARD (alpha=0.05)
drop1(model.all1, test = "F")
# quitamos Acetic del modelo por ser la de mayor p-valor
model.updateB1 <- update(model.all1, . ~ . - Acetic)
drop1(model.updateB1, test = "F")
# quitamos H2S del modelo por ser la de mayor p-valor
model.updateB2 <- update(model.updateB1, . ~ . - H2S)
drop1(model.updateB2, test = "F")
# termina el proceso pues el p-valor de Lactic no llega a alpha
model.1 <- lm(taste ~ Lactic, data = cheddar[train.1,])
summary(model.1)
# Para evitar repetir este proceso usamos el package mixlm con el que obtenemos los mismos resultados.
model.1 <- mixlm::backward(model.all1, alpha=0.05)
summary(model.1) # LACTIC
model.2 <- mixlm::backward(model.all2, alpha=0.05)
summary(model.2) # H2S + LACTIC
model.3 <- mixlm::backward(model.all3, alpha=0.05)
summary(model.3) # H2S + LACTIC
# ii) FORWARD (alpha=0.05)
SCOPE <- (~ . + Acetic + H2S + Lactic)
model.inicial <- lm(taste ~ 1, data = cheddar[train.1,]) # solo con termino independiente
add1(model.inicial, scope = SCOPE, test = "F")
# Añadimos Lactic por ser la variable predictora con menor p-valor
model.updateF1 <- update(model.inicial, . ~ . + Lactic)
add1(model.updateF1, scope = SCOPE, test = "F")
# No añadimos ninguna variable pues todos los p-valores superan la barrera de alpha
model.1a <- lm(taste ~ Lactic, data = cheddar[train.1,])
summary(model.1a)
# Al igual que en BACKWARD usamos el paquete mixlm para automatizar el proceso de FORWARD.
model.1a <- mixlm::forward(model.all1, alpha=0.05)
summary(model.1a) # LACTIC
model.2a <- mixlm::forward(model.all2, alpha=0.05)
summary(model.2a) # H2S + LACTIC
model.3a <- mixlm::forward(model.all3, alpha=0.05)
summary(model.3a) # H2S + LACTIC
# Nótese que los modelos obtenidos por BACKWARD y FORWARD coinciden para cada conjunto train.
# iii) CRITERIOS
# R2 ajustado
models1 <- regsubsets(taste ~ ., data = cheddar[train.1,])
models2 <- regsubsets(taste ~ ., data = cheddar[train.2,])
models3 <- regsubsets(taste ~ ., data = cheddar[train.3,])
summary(models1)
summary(models2)
summary(models3)
MR2adj1 <- summary(models1)$adjr2
MR2adj2 <- summary(models2)$adjr2
MR2adj3 <- summary(models3)$adjr2
summary(models1)$which[which.max(MR2adj1), ]
summary(models2)$which[which.max(MR2adj2), ]
summary(models3)$which[which.max(MR2adj3), ]
# Cp de Mallows
MCp1 <- summary(models1)$cp
MCp2 <- summary(models2)$cp
MCp3 <- summary(models3)$cp
summary(models1)$which[which.min(MCp1), ]
summary(models2)$which[which.min(MCp2), ]
summary(models3)$which[which.min(MCp3), ]
# Criterio de Informacion de Bayes (BIC)
MBIC1 <- summary(models1)$bic
MBIC2 <- summary(models2)$bic
MBIC3 <- summary(models3)$bic
summary(models1)$which[which.min(MBIC1), ]
summary(models2)$which[which.min(MBIC2), ]
summary(models3)$which[which.min(MBIC3), ]
# Criterio de Informacion de Akaike (AIC)
stepAIC(model.all1, scope = SCOPE, k = 2)
stepAIC(model.all2, scope = SCOPE, k = 2)
stepAIC(model.all3, scope = SCOPE, k = 2)
# Para el conjunto train.1 aparecen modelos con Lactic y H2S + Lactic como variables predictoras,
# mientras que para los conjuntos train.2 y train.3 unicamente aparece el modelo taste ~ H2S + Lactic.
model.1crit <- lm(taste ~ H2S + Lactic, data=cheddar[train.1,])
# Esto nos puede llevar a pensar que el modelo final vaya a ser el que utiliza H2S y Lactic.
model.1
model.1crit
model.2
model.3
anova(model.1,model.all1)
anova(model.1crit,model.all1)
anova(model.2,model.all2)
anova(model.3,model.all3)
# De esta forma vemos que los modelos creados son mejores que los completos.
# 4) Diagnostico. Comprobaciones de hipotesis, outliers y observaciones influyentes
# Comprobacion de hipotesis de los modelos
# Linealidad
resettest(model.1, power=2:3, type="regressor", data=cheddar[train.1,])
resettest(model.1crit, power=2:3, type="regressor", data=cheddar[train.1,])
resettest(model.2, power=2:3, type="regressor", data=cheddar[train.2,])
resettest(model.3, power=2:3, type="regressor", data=cheddar[train.3,])
# p-valores > 0.05 luego aceptamos hipótesis de linealidad en todos los casos
plot(cheddar$H2S, cheddar$taste,
main = "Relacion entre Taste y H2S",
xlab = "H2S", ylab = "Taste",
pch = 19, frame = FALSE)
plot(cheddar$Lactic, cheddar$taste,
main = "Relacion entre Taste y Lactic",
xlab = "Lactic", ylab = "Taste",
pch = 19, frame = FALSE)
# Normalidad y Autocorrelacion
shapiro.test(resid(model.1)) # p-valor > 0.05 no se rechaza la hipótesis nula, i.e. la normalidad
qqnorm(resid(model.1))
qqline(resid(model.1))
shapiro.test(resid(model.1crit))#bien
qqnorm(resid(model.1crit))
qqline(resid(model.1crit))
shapiro.test(resid(model.2))#bien
qqnorm(resid(model.2))
qqline(resid(model.2))
shapiro.test(resid(model.3))#bien
qqnorm(resid(model.3))
qqline(resid(model.3))
# Observamos que las colas no siguen el mismo patrón que el resto de datos, lo que podría indicar que
# el modelo no sigue una distribución normal. Sin embargo, al no afectar a un gran porcentaje de los datos y
# teniendo en cuenta el resultado previo obtenido por el Test de Shapiro-Wilk no rechazamos la hipótesis de normalidad.
# Media de errores nula
t.test(resid(model.1), mu = 0, alternative = "two.sided")
t.test(resid(model.1crit), mu = 0, alternative = "two.sided")
t.test(resid(model.2), mu = 0, alternative = "two.sided")
t.test(resid(model.3), mu = 0, alternative = "two.sided")
# p-valores ~ 1 > 0.05 luego aceptamos la hipotesis nula en todos los casos
# Autocorrelacion
durbinWatsonTest(model.1)
durbinWatsonTest(model.1crit)
durbinWatsonTest(model.2)
durbinWatsonTest(model.3)
# p-valores > 0.05 luego rechazamos que haya autocorrelacion
# Homocedasticidad
fmodel1 <- fortify(model.1)
fmodel1crit <- fortify(model.1crit)
fmodel2 <- fortify(model.2)
fmodel3 <- fortify(model.3)
X1 <- fmodel1$.fitted
Y1 <- fmodel1$.stdresid
X1crit <- fmodel1crit$.fitted
Y1crit <- fmodel1crit$.stdresid
X2 <- fmodel2$.fitted
Y2 <- fmodel2$.stdresid
X3 <- fmodel3$.fitted
Y3 <- fmodel3$.stdresid
plot(X1, Y1, ylab = "Residuos estandarizados", xlab = "valores ajustados")
plot(X1crit, Y1crit, ylab = "Residuos estandarizados", xlab = "valores ajustados")
plot(X2, Y2, ylab = "Residuos estandarizados", xlab = "valores ajustados")#casi casi hay patron
plot(X3, Y3, ylab = "Residuos estandarizados", xlab = "valores ajustados")
# Los residuos se distribuyen de forma homogénea a lo largo de una banda horizontal, luego se verifica la hipótesis nula
ncvTest(model.1)
ncvTest(model.1crit)
ncvTest(model.2)
ncvTest(model.3)
# p-valores > 0.05, luego no hay evidencia para rechazar que la varianza sea constante
# Outliers
alpha <- 0.05
n1 <- nrow(cheddar[train.1,])
p1 <- nrow(summary(model.1)$coef)
n1crit <- nrow(cheddar[train.1,])
p1crit <- nrow(summary(model.1crit)$coef)
n2 <- nrow(cheddar[train.2,])
p2 <- nrow(summary(model.2)$coef)
n3 <- nrow(cheddar[train.3,])
p3 <- nrow(summary(model.3)$coef)
# El valor critico de Bonferroni t_{1-alpha/2n;n-p-1}
BCV1 <- qt(1 - alpha / (2 * n1), n1-p1-1)
BCV1crit <- qt(1 - alpha / (2 * n1crit), n1crit-p1crit-1)
BCV2 <- qt(1 - alpha / (2 * n2), n2-p2-1)
BCV3 <- qt(1 - alpha / (2 * n3), n3-p3-1)
sum(abs(rstudent(model.1)) > BCV1)
sum(abs(rstudent(model.1crit)) > BCV1crit)
sum(abs(rstudent(model.2)) > BCV2)
sum(abs(rstudent(model.3)) > BCV3)
outlierTest(model.1)#NA?
outlierTest(model.1crit) #NA?
outlierTest(model.2)
outlierTest(model.3)
# No hay outliers en ninguno de los dos modelos planteados
# Observaciones Influyentes
# Criterio 1: valores leverage (hii) mayores que 2p/n
X1 <- model.matrix(~ H2S+Lactic, data = cheddar[train.1,])
X1crit <- model.matrix(~ H2S+Lactic, data = cheddar[train.1,])
X2 <- model.matrix(~ H2S+Lactic, data = cheddar[train.2,])
X3 <- model.matrix(~ Lactic, data = cheddar[train.3,])
H1 <- X1 %*% solve(t(X1) %*% X1) %*% t(X1)
H1crit <- X1crit %*% solve(t(X1crit) %*% X1crit) %*% t(X1crit)
H2 <- X2 %*% solve(t(X2) %*% X2) %*% t(X2)
H3 <- X3 %*% solve(t(X3) %*% X3) %*% t(X3)
hii1 <- diag(H1)
hii1crit <- diag(H1crit)
hii2 <- diag(H2)
hii3 <- diag(H3)
hCV1 <- 2 * p1 / n1
hCV1crit <- 2 * p1crit / n1crit
hCV2 <- 2 * p2 / n2
hCV3 <- 2 * p3 / n3
sum(hii1 > hCV1)
which(hii1>hCV1)#1 5 16 23 24 26
sum(hii1crit > hCV1crit)
which(hii1crit>hCV1crit)
sum(hii2 > hCV2)
which(hii2>hCV2)
sum(hii3 > hCV3)
# Criterio 2: valores |DFFITS| son mayores que 2*sqrt(p/n)
dffitsCV1 <- 2 * sqrt(p1 / n1)
dffitsCV1crit <- 2 * sqrt(p1crit / n1crit)
dffitsCV2 <- 2 * sqrt(p2 / n2)
dffitsCV3 <- 2 * sqrt(p3 / n3)
dffitsmodel1 <- dffits(model.1)
dffitsmodel1crit <- dffits(model.1crit)
dffitsmodel2 <- dffits(model.2)
dffitsmodel3 <- dffits(model.3)
sum(dffitsmodel1 > dffitsCV1)
which(dffitsmodel1 > dffitsCV1)#1 12 24
sum(dffitsmodel1crit > dffitsCV1crit)
which(dffitsmodel1crit > dffitsCV1crit)#1, 12
sum(dffitsmodel2 > dffitsCV2)
sum(dffitsmodel3 > dffitsCV3)
# Criterio 3: valores |DFBETAS| mayores que 2/sqrt(n)
dfbetaCV1 <- 2 / sqrt(n1)
dfbetaCV1crit <- 2 / sqrt(n1crit)
dfbetaCV2 <- 2 / sqrt(n2)
dfbetaCV3 <- 2 / sqrt(n3)
dfbetamodel1 <- dfbeta(model.1)
dfbetamodel1crit <- dfbeta(model.1crit)
dfbetamodel2 <- dfbeta(model.2)
dfbetamodel3 <- dfbeta(model.3)
sum(dfbetamodel1[, 1] > dfbetaCV1)
sum(dfbetamodel1[, 2] > dfbetaCV1)
which(dfbetamodel1[, 1] > dfbetaCV1)
which(dfbetamodel1[, 2] > dfbetaCV1)
sum(dfbetamodel1crit[, 1] > dfbetaCV1crit)
sum(dfbetamodel1crit[, 2] > dfbetaCV1crit)
sum(dfbetamodel1crit[, 3] > dfbetaCV1crit)
which(dfbetamodel1crit[, 1] > dfbetaCV1crit)
which(dfbetamodel1crit[, 3] > dfbetaCV1crit)
sum(dfbetamodel2[, 1] > dfbetaCV2)
sum(dfbetamodel2[, 2] > dfbetaCV2)
sum(dfbetamodel2[, 3] > dfbetaCV2)
which(dfbetamodel2[, 1] > dfbetaCV2)
which(dfbetamodel2[, 3] > dfbetaCV2)
sum(dfbetamodel3[, 1] > dfbetaCV3)
sum(dfbetamodel3[, 2] > dfbetaCV3)
sum(dfbetamodel3[, 3] > dfbetaCV3)
which(dfbetamodel3[, 1] > dfbetaCV3)
which(dfbetamodel3[, 3] > dfbetaCV3)
# Dado que nuestro datset es pequeño, no tendremso en cuenta este metodo por dar demasiadas observaciones.
# Grafica con las distancias de Cook
influencePlot(model.1)
pos_influyentes_1 <- c(1,12,24)
influencePlot(model.1crit)
pos_influyentes_1crit <- c(1,8,12,23)
influencePlot(model.2)
pos_influyentes_2 <- c(1,6,7,8,15)
influencePlot(model.3)
pos_influyentes_3 <- c(1,7,15,19,24)
# Colinealidad
vif(model.1) # tiene sentido pues en model.1 solo hay una variable predictora
vif(model.1crit)
vif(model.2)
vif(model.3) # como los valores de VIF no son grando, no indican colinealidad grave
# Vamos a tomar como posibles influyentes las que aparecen por varios metodos en cada modelo
# En el 1: 1 12
pos_1 <- c(TRUE,rep(FALSE,10),TRUE,rep(FALSE,18))
train.1inf <- train.1&!pos_1
model.1inf <- lm(taste ~ Lactic, data = cheddar[train.1inf,])
ncvTest(model.1)
ncvTest(model.1inf) # empeora pero sigue cumpliendo la hipotesis
shapiro.test(resid(model.1))
shapiro.test(resid(model.1inf)) # mejora poco
durbinWatsonTest(model.1)
durbinWatsonTest(model.1inf) # mejora
resettest(model.1, power=2:3, type="regressor", data=cheddar[train.1inf,])
resettest(model.1inf, power=2:3, type="regressor", data=cheddar[train.1inf,]) # mejora bastante
# Redefinimos el modelo eliminando las observaciones influyentes de pos_1.
train.1aux<-train.1
train.1 <- train.1inf
model.1 <- model.1inf
# En el 1crit: 1 12 23
pos_1crit <- c(TRUE,rep(FALSE,10),TRUE,rep(FALSE,10),TRUE,rep(FALSE,7))
train.1critinf <- train.1&!pos_1crit
model.1critinf <- lm(taste ~H2S+Lactic , data = cheddar[train.1critinf,])
ncvTest(model.1crit)
ncvTest(model.1critinf) # empeora
shapiro.test(resid(model.1crit))
shapiro.test(resid(model.1critinf)) # mejora
durbinWatsonTest(model.1crit)
durbinWatsonTest(model.1critinf) # mejora bastante
resettest(model.1crit, power=2:3, type="regressor", data=cheddar[train.1,])
resettest(model.1critinf, power=2:3, type="regressor", data=cheddar[train.1critinf,]) # empeora dentro de aceptable
# Redefinimos el modelo eliminando las observaciones influyentes de pos_1crit.
train.1crit <- train.1critinf
model.1crit <- model.1critinf
# En el 2: 6
pos_2 <- c(rep(FALSE,5),TRUE,rep(FALSE,24))
train.2inf <- train.2&!pos_2
model.2inf <- lm(taste ~ H2S+Lactic, data = cheddar[train.2inf,])
ncvTest(model.2)
ncvTest(model.2inf) # mejora poco
shapiro.test(resid(model.2))
shapiro.test(resid(model.2inf)) # aproximadamente lo mismo
durbinWatsonTest(model.2)
durbinWatsonTest(model.2inf) # mejora
resettest(model.2, power=2:3, type="regressor", data=cheddar[train.2inf,])
resettest(model.2inf, power=2:3, type="regressor", data=cheddar[train.2inf,]) # aproximadamente lo mismo
# Redefinimos el modelo eliminando las observaciones influyentes de pos_2.
train.2 <- train.2inf
model.2 <- model.2inf
# En el modelo 3 no hacemos comprobaciones nada ya que no se repiten observaciones por distintos metodos.
# 5) Errores de Test. Comparacion de Modelos
# Vamos a considerar otras dos semillas para evaluar los modelos y elegir el mejor.
# Las tomamos de forma que no coincidan en la medida de lo posible los tests de las distintas particiones.
# Dividimos el conjunto total para las dos semillas nuevas.
set.seed((2234))
train.4 <- sample(c(TRUE, FALSE), size = nrow(cheddar), replace = TRUE, prob = c(0.7, 0.3))
test.4 <- (!train.4)
sum(test.4)
sum(test.1==TRUE & test.4==TRUE)
sum(test.2==TRUE & test.4==TRUE)
sum(test.3==TRUE & test.4==TRUE)
set.seed((131))
train.5 <- sample(c(TRUE, FALSE), size = nrow(cheddar), replace = TRUE, prob = c(0.7, 0.3))
test.5 <- (!train.5)
sum(test.5)
sum(test.1==TRUE & test.5==TRUE)
sum(test.2==TRUE & test.5==TRUE)
sum(test.3==TRUE & test.5==TRUE)
sum(test.4==TRUE & test.5==TRUE)
train.1h <- train.1crit
train.2h <- train.2
train.3h <- train.3
train.4h <- train.4
train.5h <- train.5
# Recalculamos train.2 porque fue modificado
set.seed(1100)
train.2 <- sample(c(TRUE, FALSE), size = nrow(cheddar), replace = TRUE, prob = c(0.7, 0.3))
# Veamso si podemos eliminar posibles influyentes en los modelos restantes
mh1 <- lm(taste ~ H2S + Lactic, data = cheddar[train.1h,]) # comprobados supuestos
mh2 <- lm(taste ~ H2S + Lactic, data = cheddar[train.2h,]) # comprobados supuestos
mh3 <- lm(taste ~ H2S + Lactic, data = cheddar[train.3h,]) # comprobados supuestos
mh4 <- lm(taste ~ H2S + Lactic, data = cheddar[train.4h,])
mh5 <- lm(taste ~ H2S + Lactic, data = cheddar[train.5h,])
m1 <- lm(taste ~ Lactic, data = cheddar[train.1,]) # comprobados supuestos
m2 <- lm(taste ~ Lactic, data = cheddar[train.2,])
m3 <- lm(taste ~ Lactic, data = cheddar[train.3,])
m4 <- lm(taste ~ Lactic, data = cheddar[train.4,])
m5 <- lm(taste ~ Lactic, data = cheddar[train.5,])
# Al igual que hicimos en 4 comprobamos si retirando outliers y observaciones influyentes mejoran las hipotesis.
# Unicamente consideraremos observaciones obtenidas tanto por outlierTest() como por influencePlot().
# mh4
outlierTest(mh4)
influencePlot(mh4) # 6,12,15,24
pos4h <- c(rep(FALSE,5),TRUE,rep(FALSE,5),TRUE,rep(FALSE,2),TRUE,rep(FALSE,8),TRUE,rep(FALSE,6))
train.4inf <- train.4h&!pos4h
mh4inf <- lm(taste ~ H2S+Lactic, data = cheddar[train.4inf,])
ncvTest(mh4)
ncvTest(mh4inf) # mejora MUCHO
shapiro.test(resid(mh4))
shapiro.test(resid(mh4inf)) # mejora
durbinWatsonTest(mh4)
durbinWatsonTest(mh4inf) # mejora
resettest(mh4, power=2:3, type="regressor", data=cheddar[train.4inf,])
resettest(mh4inf, power=2:3, type="regressor", data=cheddar[train.4inf,]) # empeora pero es aceptable
# Redefinimos eliminando pos4h por ser tanta la mejora en homocedasticidad que compensa la linealidad
train.4h <- train.4inf
mh4 <- mh4inf
# mh5
outlierTest(mh5)
influencePlot(mh5) # 6,7,8,12,15
pos5h <- c(rep(FALSE,5),TRUE,TRUE,TRUE,rep(FALSE,3),TRUE,rep(FALSE,2),TRUE,rep(FALSE,15))
train.5inf <- train.5h&!pos5h
mh5inf <- lm(taste ~ H2S+Lactic, data = cheddar[train.5inf,])
ncvTest(mh5)
ncvTest(mh5inf) # mejora
shapiro.test(resid(mh5))
shapiro.test(resid(mh5inf)) # empeora
durbinWatsonTest(mh5)
durbinWatsonTest(mh5inf) # a veces no se cumple la hipotesis nula de no autocorrelacion
resettest(mh5, power=2:3, type="regressor", data=cheddar[train.5inf,])
resettest(mh5inf, power=2:3, type="regressor", data=cheddar[train.5inf,]) # empeora
# Decidimos no actualizar el modelo pues no siempre se rechaza la correlacion y empeoran otros p-valores.
# m2
outlierTest(m2)
influencePlot(m2) # 1,12,15,18,24
pos2 <- c(TRUE,rep(FALSE,10),TRUE,rep(FALSE,2),TRUE,rep(FALSE,2),TRUE,rep(FALSE,5),TRUE,rep(FALSE,6))
train.2inf <- train.2&!pos2
m2inf <- lm(taste ~ Lactic, data = cheddar[train.2inf,])
ncvTest(m2)
ncvTest(m2inf) # empeora ligeramente
shapiro.test(resid(m2))
shapiro.test(resid(m2inf)) # empeora ligeramente
durbinWatsonTest(m2)
durbinWatsonTest(m2inf) # empeora bastante
resettest(m2, power=2:3, type="regressor", data=cheddar[train.2inf,])
resettest(m2inf, power=2:3, type="regressor", data=cheddar[train.2inf,]) # mejora
# Decicimos no redefinirlo, ya que empeora en muchas y mejora bastante en una
# m3
outlierTest(m3)
influencePlot(m3) # 1,15,19,24
pos3 <- c(TRUE,rep(FALSE,13),TRUE,rep(FALSE,3),TRUE,rep(FALSE,4),TRUE,rep(FALSE,6))
train.3inf <- train.3&!pos3
m3inf <- lm(taste ~ Lactic, data = cheddar[train.3inf,])
ncvTest(m3)
ncvTest(m3inf) # mejora poco
shapiro.test(resid(m3))
shapiro.test(resid(m3inf)) # mejora
durbinWatsonTest(m3)
durbinWatsonTest(m3inf) # empeora
resettest(m3, power=2:3, type="regressor", data=cheddar[train.3inf,])
resettest(m3inf, power=2:3, type="regressor", data=cheddar[train.3inf,]) # empeora casi lo pierde
# Decidimos no redefinirlo por estar al borde en un criterio y no mejorar mucho en otros
# m4
outlierTest(m4)
influencePlot(m4) # 6,12,15,20,24
pos4 <- c(rep(FALSE,5),TRUE,rep(FALSE,5),TRUE,rep(FALSE,2),TRUE,rep(FALSE,4),TRUE,rep(FALSE,3),TRUE,rep(FALSE,6))
train.4inf <- train.4&!pos4
m4inf <- lm(taste ~ Lactic, data = cheddar[train.4inf,])
ncvTest(m4)
ncvTest(m4inf) # empeora bastante
shapiro.test(resid(m4))
shapiro.test(resid(m4inf)) # empeora
durbinWatsonTest(m4)
durbinWatsonTest(m4inf)# empeora bastante
resettest(m4, power=2:3, type="regressor", data=cheddar[train.4inf,])
resettest(m4inf, power=2:3, type="regressor", data=cheddar[train.4inf,]) # mejora algo
# Decidimos no cambiarlo porque empeora en casi todo, y de por si tenia buenos p-values
# m5
outlierTest(m5)
influencePlot(m5) # 1,8,12,15,18,24
pos5 <- c(TRUE,rep(FALSE,6),TRUE,rep(FALSE,3),TRUE,rep(FALSE,2),TRUE,rep(FALSE,2),TRUE,rep(FALSE,5),TRUE,rep(FALSE,6))
train.5inf <- train.5&!pos5
m5inf <- lm(taste ~ Lactic, data = cheddar[train.5inf,])
ncvTest(m5)
ncvTest(m5inf) # empeora bastante
shapiro.test(resid(m5))
shapiro.test(resid(m5inf)) # mejora
durbinWatsonTest(m5)
durbinWatsonTest(m5inf) # no se verifica la hipotesis nula de no autocorrelacion
resettest(m5, power=2:3, type="regressor", data=cheddar[train.5inf,])
resettest(m5inf, power=2:3, type="regressor", data=cheddar[train.5inf,]) # empeora
# Decidimos no cambiarlo por perderse la correlación
# Notese que en los originales siempre se cumplian las hipotesis, aunque no era necesario para el proceso
lista_test <- list(test.1,test.2,test.3,test.4,test.5)
lista_trainh <- list(train.1h,train.2h,train.3h,train.4h,train.5h)
lista_train <- list(train.1,train.2,train.3,train.4,train.5)
modelos_hip <- c("S1 taste ~ H2s + Lactic",
"S1 taste ~ Lactic",
"S2 taste ~ H2s + Lactic",
"S2 taste ~ Lactic",
"S3 taste ~ H2s + Lactic",
"S3 taste ~ Lactic",
"S4 taste ~ H2s + Lactic",
"S4 taste ~ Lactic",
"S5 taste ~ H2s + Lactic",
"S5 taste ~ Lactic",
"Nivel de significacion")
hip_RL <- c("Distribución_normal",
"Media_0",
"Varianza_no_constante",
"No_Autocorrelación")
placeholder <- vector(mode = "logical",length = 11)
df_hipRL <- data.frame("0" = placeholder,
"1" = placeholder,
"2" = placeholder,
"3" = placeholder,
row.names = modelos_hip)
colnames(df_hipRL) <- hip_RL
r <- 1
for (dtrain in lista_trainh){
model.HL.lm <- lm(taste ~ H2S + Lactic,
data = cheddar[dtrain,])
residuos <- resid(model.HL.lm)
new_row <- c()
shap <- round(shapiro.test(residuos)$p.value,4)
t <- t.test(residuos, mu = 0, alternative = "two.sided")$p.value
v <- round(ncvTest(model.HL.lm)$p,4)
dw <- round(durbinWatsonTest(model.HL.lm)$p,4)
new_row = c(shap,t,v,dw)
df_hipRL[r,] <- new_row
r = r + 2
}
r <- 2
for (dtrain in lista_train){
model.L.lm <- lm(taste ~Lactic,
data = cheddar[dtrain,])
residuos <- resid(model.L.lm)
new_row <- c()
shap <- round(shapiro.test(residuos)$p.value,4)
t <- t.test(residuos, mu = 0, alternative = "two.sided")$p.value
v <- round(ncvTest(model.L.lm)$p,4)
dw <- round(durbinWatsonTest(model.L.lm)$p,4)
new_row = c(shap,t,v,dw)
df_hipRL[r,] <- new_row
r = r + 2
}
df_hipRL[11,] <- c(rep(0.05,4))
df_hipRL # Todos los modelos cumplen las hipótesis
err1 <- 0
for (i in 5){
dtrain <- lista_trainh[[i]]
dtest <- lista_test[[i]]
dmod <- lm(taste ~ H2S + Lactic, data = cheddar[dtrain,])
Y <- cheddar[dtest,]$taste
Yhat <- predict(obj = dmod, newdata = cheddar[dtest,])
err1 <- err1 + mean((Y - Yhat)^2)
}
err1 <- err1/5
err1 # H2S + LACTIC tiene error medio 11.63
err2<-0
for (i in 5){
dtrain <- lista_train[[i]]
dtest <- lista_test[[i]]
dmod <- lm(taste ~ Lactic, data = cheddar[dtrain,])
Y <- cheddar[dtest,]$taste
Yhat <- predict(obj = dmod, newdata = cheddar[dtest,])
err2 <- err2 + mean((Y - Yhat)^2)
}
err2 <- err2/5
err2 # LACTIC tiene error medio 19.4
err1 < err2 # Concluimos que el modelo taste ~ H2S + Lactic es mejor que taste ~ Lactic.
# 6) Conclusion
model.y <- lm(taste ~ H2S + Lactic,data=cheddar) # tomamos el mejor modelo de los obtenidos en 4
summary(model.y)
plot(model.y)
# Veamos los posibles outliers
outlierTest(model.y)
influencePlot(model.y)
# Estudio de hipótesis supuestas
shapiro.test(resid(model.y)) # normalidad de residuos
t.test(resid(model.y), mu = 0, alternative = "two.sided") # media cero de los residuos
ncvTest(model.y) # varianza constante de los residuos
durbinWatsonTest(model.y) # no autocorrelacion
resettest(model.y ,power=2:3, type="regressor", data=cheddar) # linealidad
# Efectivamente, cumple todas las hipótesis
summary(model.y) # en el summary observamos los valores de betahat, sus p-valores y sigma
coeff <- summary(model.y)$coeff[,1]
coeff
# Calculo de intervalo de confianza de beta1(H2S) y beta2(Lactic)
# Metodo Bonferroni
alpha <- 0.10
summary(model.y)$coef
b <- summary(model.y)$coef[2:3, 1]
s.b <- summary(model.y)$coef[2:3, 2]
g <- 3
n <- nrow(cheddar)
p <- ncol(summary(model.y)$coef)
t_teo <- qt(1 - alpha / (2 * g), n - p)
BomSimCI <- matrix(c(b - t_teo * s.b, b + t_teo * s.b), ncol = 2)
conf <- c("5%", "95%")
bnam <- c("H2S", "Lactic")
dimnames(BomSimCI) <- list(bnam, conf)
BomSimCI
# Intervalo de confianza simultaneo por el metodo de Scheffe
Q <- p - 1
f_teo <- qf(0.9, Q, n - p)#0.9 no seria 0.95?
SchSimCI <- matrix(c(b - sqrt(Q * f_teo) * s.b, b + sqrt(Q * f_teo) * s.b), ncol = 2)
conf <- c("5%", "95%")
bnam <- c("H2S", "Lactic")
dimnames(SchSimCI) <- list(bnam, conf)
SchSimCI
# La ecuación de nuestro modelo final es y = (-27.6) + 3.95*x_H + 19.9*x_L,
# donde x_H y x_L denotan los valores observados de H2S y Lactic.
rse <- sqrt(deviance(model.y)/df.residual(model.y))
rse # varianza de los residuos
pval <- summary(model.y)$coeff[,4]
pval # vector con los p-valores
# Calculo de su R^2
anova(model.y)
SSE <- anova(model.y)[3,2]
SST <- anova(model.y)[1,2]+anova(model.y)[2,2]+anova(model.y)[3,2]
rsqr <- 1 - SSE/SST
rsqr
summary(model.y)$r.squared# es la misma
# Calculo de su R^2 ajustada
MSE <- SSE/anova(model.y)[3,1]
MST <- SST/(anova(model.y)[1,1]+anova(model.y)[2,1]+anova(model.y)[3,1])
Radj <-1-MSE/MST
Radj # se comprueba en la tabla summary que el valor es correcto
# Observamos como se distribuye la variable taste en función de H2S y Lactic
plot_ly(x=H2S, y=Lactic, z=taste, type="scatter3d", mode="marker", color=taste) %>%
layout(scene = list(xaxis = list(title = 'H2S (%)'),
yaxis = list(title = 'Lactic (%)'),
zaxis = list(title = 'Taste (0-100)')))
# Vemos el plano de regresion del modelo propuesto.
# En rojo se marcan las observaciones que peor se ajustan al modelo.
planereg <- scatterplot3d(x=H2S, y=Lactic, z=taste, pch=16, cex.lab=1,
highlight.3d=TRUE, type="h", xlab='H2S (%)',
ylab='Lactic (%)', zlab='Taste (0-100)')
planereg$plane3d(model.y, lty.box="solid", col='mediumblue')
LS0tDQp0aXRsZTogJ1JlZ3Jlc2nDs246IE1vZGVsb3MgRXN0YWTDrXN0aWNvcycNCmF1dGhvcjoNCi0gRGFuaWVsIEzDs3BleiBNb250ZXJvDQotIFJvZHJpZ28gZGUgbGEgTnVleiBNb3JhbGVkYQ0KLSBKb3PDqSBHYXJjw61hIFJlYm9sbG8NCi0gRGF2aWQgUGFycm8gUGxhemEgDQpvdXRwdXQ6DQogIHBkZl9kb2N1bWVudDoNCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcw0KICBodG1sX2RvY3VtZW50Og0KICAgIHRvYzogeWVzDQogICAgdG9jX2RlcHRoOiAzDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgICBkZl9wcmludDogcGFnZWQNCiAgd29yZF9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogJzMnDQogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQNCmFsd2F5c19hbGxvd19odG1sOiB5ZXMNCmFic3RyYWN0OiB8DQogIEhlbW9zIGFuYWxpemFkbyBjb24gbGFzIGhlcnJhbWllbnRhcyBwcm9wb3JjaW9uYWRhcyBlbiBlbCBjdXJzbyBkZSBNb2RlbG9zIEVzdGFkw61zdGljb3MgZWwgY29uanVudG8gZGUgZGF0b3MsICpDaGVkZGFyKiwgZGlzdHJpYnVpZG8gZW4gbGEgbGlicmVyw61hIEZhcmF3YXkgZGUgUi4gUGFyYSBlbGxvIGhlbW9zIHV0aWxpemFkbyBkaXZlcnNhcyB0w6ljbmljYXMgZGUgcmVncmVzacOzbiBsaW5lYWwuDQpzdWJ0aXRsZTogJ0Nvbmp1bnRvIGRlIERhdG9zOiBDaGVkZGFyIEZhcmF3YXknDQotLS0NCg0KDQojIEludHJvZHVjY2nDs24NCg0KRW4gdW4gZXN0dWRpbyBkZSBxdWVzbyBDaGVkZGFyIHJlYWxpemFkbyBlbiBlbCBWYWxsZSBkZSBMYXRyb2JlIChWaWN0b3JpYSwgQXVzdHJhbGlhKSwgc2UgZXN0dWRpYXJvbiBtdWVzdHJhcyBkZSBxdWVzbyBlbiBsYXMgcXVlIHNlIGFuYWxpesOzIHN1IGNvbXBvc2ljacOzbiBxdcOtbWljYSB5IGZ1ZXJvbiBkYWRhcyBhIHByb2JhciBhIGRpc3RpbnRvcyBzdWpldG9zIHBhcmEgcXVlIHZhbG9yYXJhbiBzdSBzYWJvci4gTG9zIHZhbG9yZXMgYXNpZ25hZG9zIGEgY2FkYSBxdWVzbyBzb24gZWwgcmVzdWx0YWRvIGRlIGNvbWJpbmFyIGxhcyBkaXN0aW50YXMgdmFsb3JhY2lvbmVzLiANCg0KRWwgRGF0YUZyYW1lICoqY2hlZGRhcioqIGRlIGxhIGxpYnJlcsOtYSAqKmZhcmF3YXkqKiBjb25zaXN0ZSBkZSAzMCBtdWVzdHJhcyBkZSBxdWVzbyBDaGVkZGFyIGVuIGxhcyBxdWUgc2UgaGEgbWVkaWRvIGVsIHNhYm9yICgqdGFzdGUqKSB5IGxhcyBjb25jZW50cmFjaW9uZXMgZGUgw6FjaWRvIGFjw6l0aWNvICgqQWNldGljKiksIMOhY2lkbyBzdWxmaMOtZHJpY28gKCpIMlMqKSB5IGxhY3Rvc2EgKCpMYWN0aWMqKS4NCg0KDQpUZW5lbmVtb3MgdW4gY29uanVudG8gZGUgZGF0b3MgZW4gZWwgcXVlIHNlIHJlY29nZW4gb2JzZXJ2YWNpb25lcyBkZSB1bmEgY2F0YSBkZQ0KcXVlc29zLCBudWVzdHJhcyB2YXJpYWJsZXMgc29uOiAgIA0KDQoNCioqwrcgVGFzdGU6KiogdW5hIHZhbG9yYWNpw7NuIHN1YmpldGl2YSBkZSBsb3MganVlY2VzLiAgIA0KDQoqKsK3IEFjZXRpYzoqKiBsYSBjb25jZW50cmFjacOzbiBkZSDDoWNpZG8gYWPDqXRpY28uDQoNCioqwrcgSDJTOioqIGxhIGNvbmNlbnRyYWNpw7NuIGRlIHN1bGZpdG8gZGUgaGlkcsOzZ2Vuby4NCg0KKirCtyBMYWN0aWM6KiogY29uY2VudHJhY2nDs24gZGUgw6FjaWRvIGzDoWN0aWNvLg0KDQogPCEtLSBBIGxvIGxhcmdvIGRlbCBkb2N1bWVudG8gaGFjZW1vcyB1c28gZGUgbGFzIHNpZ3VpZW50ZXMgbGlicmVyaWFzIGRlIFI6IC0tPg0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRSwgaW5jbHVkZT1GQUxTRSwgcGFnZWQucHJpbnQ9VFJVRX0NCmxpYnJhcnkoZmFyYXdheSkNCmxpYnJhcnkobGVhcHMpDQpsaWJyYXJ5KE1BU1MpDQpsaWJyYXJ5KFBBU1dSKQ0KbGlicmFyeShjYXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHBseXIpDQpsaWJyYXJ5KEdHYWxseSkNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoc2NhdHRlcnBsb3QzZCkNCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShtaXhsbSkNCmxpYnJhcnkoY293cGxvdCkNCmxpYnJhcnkoa25pdHIpDQpsaWJyYXJ5KGxlbW9uKQ0KbGlicmFyeShicm9vbSkNCmxpYnJhcnkodGliYmxlKQ0KYGBgDQoNCkNhcmdhbW9zIGxvcyBkYXRvcyB5IGVuc2XDsWFtb3MgbGFzIHByaW1lcmFzIG9ic2VydmFjaW9uZXMuDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQojIGxvYWQgY2hlZGRhciBjaGVkZGFyDQpkYXRhKGNoZWRkYXIpIA0KaGVhZChjaGVkZGFyKQ0KYGBgDQoNClNpIGVuIG51ZXN0cm8gZGF0YXNldCB0dXZpZXNlbW9zIGVudHJhZGFzIHZhY8OtYXMgKE5BKSwgdGVuZW1vcyB2YXJpYXMgcG9zaWJpbGlkYWRlcyBwYXJhIGxpZGlhciBjb24gZXN0ZSBwcm9ibGVtYToNCg0KKiBObyB1dGlsaXphci9FbGltaW5hciBsYXMgb2JzZXJ2YWNpw7NuIHF1ZSBjb250aWVuZW4gdmFsb3Jlcy4NCg0KKiBObyB1dGlsaXphci9FbGltaW5hciBsYXMgdmFyaWFibGVzIHF1ZSBjb250aWVuZW4gbGFzIGVudHJhZGFzIHZhY8OtYXMuDQoNCiogSW50ZW50YXIgY29tcGxldGFyIGxvcyB2YWxvcmVzLiBFeGlzdGVuIG3DqXRvZG9zIG1lbm9zIHkgbcOhcyBzb2Zpc2l0Y2Fkb3M6DQoNCiAgKyBSZW1wbGV6YXIgY29uIGxhICoqbWVkaWEsIG1lZGlhIG8gbW9kYSoqLg0KDQogICsgQ3JlYXIgdW5hICoqbnVldmEgY2F0ZWdvcsOtYSoqIHBhcmEgdmFsb3JlcyB2YWPDrW9zLg0KDQogICsgVXRpbGl6YXIgYWxnw7puIG1vZGVsbyBkZSAqKnJlZ3Jlc2nDs24qKi4NCg0KICArIFVzYXIgdW4gbW9kZWxvIGRlICoqSy1OZWFyZXN0IE5laWdoYm9ycyAoS05OKSoqLg0KICANClBlcm8gZW4gbnVlc3RybyBjYXNvIGV2YWx1YW1vcyB5IG5vIGhheSB2YWxvcmVzICptaXNzaW5nKi4gIA0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KIyBjaGVjayBpZiBhbnkgZW50cnkgaGFzIGEgbWlzc2luZyB2YWx1ZSAoTkEpDQphbnkoaXMubmEoY2hlZGRhcikpDQpgYGANCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Kc2FwcGx5KGNoZWRkYXIsIGNsYXNzKQ0KYGBgDQoNCkVuIG51ZXN0cm8gY2FzbywgdG9kYXMgbGFzIHZhcmlhYmxlcyBzb24gbnVtw6lyaWNhcyAoKipjdWFudGl0YXRpdmFzKiopLiBObyBoYXkgbmluZ3VuYSB2YXJpYWJsZSBjYXRlZ8OzcmljYSBuaSBjdWFsaXRhdGl2YS4gU2kgaHViaWVzZSwgdGVuZHLDrWFtb3MgcXVlIHRyYW5zZm9ybWFybGFzIGVuIHZhcmlhYmxlcyBiaW5hcmlhcy4gUGFyYSBlbGxvLCBkZWJlcsOtYW1vcyBoYWNlciBlbmNvZGluZyBhIHZhcmlhYmxlcyBiaW5hcmlhcywgZWwgbGVuZ3VhamUgZGUgcHJvZ3JhbWFjacOzbiBSIG5vcyBwZXJtaXRlIHV0aWxpemFyICphcy5udW1lcmljKi4NCg0KQ29uIGVzdGFzIHZhcmlhYmxlcyB2YW1vcyBhIGludGVudGFyICoqZXhwbGljYXIqKiBjw7NtbyBsb3MgdmFsb3JlcyBvYnNlcnZhZG9zIGRlIHVuYSB2YXJpYWJsZSBZICh0YXN0ZSkgZGVwZW5kZW4gZGUgbG9zIHZhbG9yZXMgZGUgb3RyYXMgdmFyaWFibGVzIChBY2V0aWMsIEgyUywgTGF0Y2ljKSwgYSB0cmF2w6lzIGRlIHVuYSByZWxhY2nDs24gZnVuY2lvbmFsIGxpbmVhbCBkZWwgdGlwbyBZID0gZihYKS4NClRhbWJpw6luIHZhbW9zIGEgaW50ZW50YXIgKipwcmVkZWNpcioqIGVsIHZhbG9yIGRlIGxhIHZhcmlhYmxlIFkgcGFyYSB2YWxvcmVzIG5vIG9ic2VydmFkb3MgZGUgbGFzIHZhcmlhYmxlcyBYLg0KDQoNClRlbmVtb3MgMzAgb2JzZXJ2YWNpb25lcyBlbiBudWVzdHJvIGRhdGFzZXQuIEFob3JhIHByb2NlZGVtb3MgYSBkaXZpcmxvIGVuIGVsICpjb25qdW50byBkZSB0cmFpbiB5IHRlc3QqLiBFbCBwcmltZXJvIGxvIHV0aWxpemFyZW1vcyBwYXJhIGVudHJlbmFyIG51ZXN0cm9zIG1vZGVsb3MgeSBlbCBzZWd1bmRvIGxvIHVzYXJlbW9zIHBhcmEgY3VhbnRpZmljYXIgZWwgZXJyb3IgZGUgbG9zIG1vZGVsb3MuDQoNCg0KUGFyYSBhc2VndXJhciBxdWUgc2VhIHJlcHJvZHVjaWJsZSB1dGlsaXphbW9zIHVuYSBzZW1pbGxhLCBxdWUgcGVybWl0ZSBmaWphciBsb3MgdmFsb3JlcyBwc2V1ZG9hbGVhdG9yaW9zIG9idGVuaWRvcyBlbiBtdWNoYXMgZGUgbGFzIGZ1bmNpb25lcyB1dGlsaXphZGFzLg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCiMgUGFyYSBhc2VndXJhciBxdWUgc2VhIHJlcHJvZHVjaWJsZSB1dGlsaXphbW9zIHVuYSBzZW1pbGxhLCBxdWUgcGVybWl0ZSBmaWphciBsb3MgdmFsb3JlcyBwc2V1ZG9hbGVhdG9yaW9zIG9idGVuaWRvcyBlbiBtdWNoYXMgZGUgbGFzIGZ1bmNpb25lcyB1dGlsaXphZGFzLg0Kc2V0LnNlZWQoMSkNCnRyYWluIDwtIHNhbXBsZShjKFRSVUUsIEZBTFNFKSwNCiAgICAgICAgICAgICAgICBzaXplID0gbnJvdyhjaGVkZGFyKSwNCiAgICAgICAgICAgICAgICByZXBsYWNlID0gVFJVRSwNCiAgICAgICAgICAgICAgICBwcm9iID0gYygwLjcsIDAuMykpDQp0ZXN0IDwtICF0cmFpbg0KYGBgDQoNCkhhY2Vtb3MgdW4gZXN0dWRpbyBwcmVsaW1pbmFyIGRlIG51ZXN0cmFzIHZhcmlhYmxlcy4gTW9zdHJhbW9zIHVuIHNjYXR0ZXIgcGxvdCBkZSBjYWRhIHZhcmlhYmxlIGNvbnRyYXN0YWRhIGNvbiBlbCByZXN0by4gRXN0byBwZXJtaXRlIHZlciAqYSBvam8qIHNpIGFsZ8O6biBwYXIgZGUgdmFyaWFibGVzIHRpZW5lIGNvcnJlbGFjacOzbi4gIA0KDQpgYGB7ciBlY2hvPUZBTFNFLCxmaWcud2lkdGg9NyxmaWcuaGVpZ2h0PTR9DQpwbG90KGNoZWRkYXIpDQpgYGANCiAgDQogIEFob3JhLCB1dGlsaXphbW9zIGxhIGZ1bmNpw7NuICpzdW1tYXJ5KiBkZSBSLCBsYSBjdWFsIG5vcyBwZXJtaXRlIGVzdGltYXIgYWxndW5vcyBkZSBsYXMgY2FyYWN0ZXLDrXN0aWNhcyBkZSBsYSBkaXN0cmlidWNpw7NuIGRlbCBkYXRhc2V0LiBMYSBzaWd1aWVudGUgdGFibGEgbm9zIG11ZXN0cmEgbG9zIGVzdGFkw61zdGljb3MgbcOhcyBjb211bmVzOiBlbCBtw61uaW1vLCBtw6F4aW1vLCBtZWRpYW5hLCBtZWRpYSB5IGVsIDFlciB5IDNlciBjdWFydGlsLiANCg0KDQpgYGB7ciBmaWcud2lkdGg9NSwgaW5jbHVkZT1GQUxTRX0NCmRmX3Jlc3VtZW4gPC0gdGlkeShjaGVkZGFyKSAjIERpc3RyaWJ1Y2nDs24gZGUgbGFzIHZhcmlhYmxlcw0KDQoNCg0KDQpgYGANCjxicj4NCjxicj4NCjxicj4NClByZXNlbnRhbW9zIGVsIG1vZGVsbzoNCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludH0NCmRhdGEuZnJhbWUobGFwcGx5KGRmX3Jlc3VtZW4sIGZ1bmN0aW9uKHkpIGlmKGlzLm51bWVyaWMoeSkpIHJvdW5kKHksIDIpIGVsc2UgeSkpDQoNCg0KYGBgDQoNCg0KDQpgYGB7ciBBdHRhY2gsIGluY2x1ZGU9RkFMU0V9DQphdHRhY2goY2hlZGRhcikNCmBgYA0KDQoNCkhhY2Vtb3MgbGFzIGdyw6FmaWNhcyBkZSBkaXNwZXJzacOzbiBlbnRyZSBsYSB2YXJpYWJsZSByZXNwdWVzdGEgKnRhc3RlKiB5IGxhcyB2YXJpYWJsZXMgcHJlZGljdG9yYXMgKkFjZXRpYywgSDJTLCBMYWN0aWMqLg0KDQpgYGB7ciBlY2hvPUZBTFNFLGZpZy53aWR0aD03LGZpZy5oZWlnaHQ9M30NCmxheW91dChtYXRyaXgoMTozLCBucm93ID0gMSkpDQojIHBsb3QgdGFzdGUgfiBBY2V0aWMNCnBsb3QoQWNldGljLCB0YXN0ZSwNCiAgICAgbWFpbiA9ICJSZWxhY2nDs24gZW50cmUgVGFzdGUgeSBBY2V0aWMiLA0KICAgICB4bGFiID0gIkFjZXRpYyIsIHlsYWIgPSAiVGFzdGUiLA0KICAgICBwY2ggPSAxOSwgZnJhbWUgPSBGQUxTRSkNCiMgcGxvdCB0YXN0ZSB+IEgyUw0KcGxvdChIMlMsIHRhc3RlLA0KICAgICBtYWluID0gIlJlbGFjacOzbiBlbnRyZSBUYXN0ZSB5IEgyUyIsDQogICAgIHhsYWIgPSAiSDJTIiwgeWxhYiA9ICJUYXN0ZSIsDQogICAgIHBjaCA9IDE5LCBmcmFtZSA9IEZBTFNFKQ0KIyBwbG90IHRhc3RlIH4gTGFjdGljDQpwbG90KExhY3RpYywgdGFzdGUsDQogICAgIG1haW4gPSAiUmVsYWNpw7NubiBlbnRyZSBUYXN0ZSB5IExhY3RpYyIsDQogICAgIHhsYWIgPSAiTGFjdGljIiwgeWxhYiA9ICJUYXN0ZSIsDQogICAgIHBjaCA9IDE5LCBmcmFtZSA9IEZBTFNFKQ0KYGBgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpsYXlvdXQobWF0cml4KDE6MSwgbnJvdyA9IDEpKQ0KYGBgDQoNClBvZGVtb3Mgb2JzZXJ2YXIgcXVlIGxhIHF1ZSBhcGVyZW50ZW1lbnRlIGd1YXJkYSB1bmEgbWVub3IgcmVsYWNpw7NuIGxpbmVhbCBjb24gdGFzdGUgZXMgbGEgdmFyaWFibGUgQWNldGljLCBlc3RlIGhlY2hvIHNlcsOhIHJlYWZpcm1hZG8gbcOhcyBhZGVsYW50ZS4NCg0KDQojIEVzdHVkaW8geSBldmFsdWFjacOzbiBkZWwgbW9kZWxvIGNvbXBsZXRvLiAgDQoNCkludGVudGFyZW1vcyBwcmVkZWNpciBsYSB2YXJpYWJsZSAqdGFzdGUqIHVzYW5kbyBlbCByZXN0byBkZSB2YXJpYWJsZXMuIFBhcmEgZW1wZXphciwgZGVmaW5pbW9zIGVsIG1vZGVsbyBjb21wbGV0bywgZWwgY3VhbCBzZSB1c2FuIHRvZGFzIGxhcyB2YXJpYWJsZXMgcGFyYSBudWVzdHJvIG1vZGVsbyBsaW5lYWwgbcO6bHRpcGxlLg0KDQokJA0KWV9pID1cYmV0YV8wICsgXGJldGFfMSB4X3tpMX0gKyBcZG90cyArIFxiZXRhX3twLTF9eF97aShwLTEpfSArIFxlcHNpbG9uX2ksXHF1YWQgaT0xLFxkb3RzLG4NCiQkDQpkb25kZSAkWV9pJCBlcyBlbCB2YWxvciBkZSBsYSB2YXJpYWJsZSByZXNwdWVzdGEgcGFyYSBlbCBpbmRpdmlkdW8gJGkkLcOpc2ltbywgDQokXGJldGFfMCQgeSBsb3MgJFxiZXRhX2okIHNvbiBsb3MgcGFyw6FtZXRyb3MgJGogPSAxLCAuLi4sIHAgLSAxJCwgDQokeF97aWp9JCBzb24gbG9zIGVsZW1lbnRvcyBkZSBsYSBtYXRyaXogZGUgbGFzIHZhcmlhYmxlcyBleHBsaWNhdGl2YXMgDQokXGVwc2lsb25faSQgZXMgZWwgdMOpcm1pbm8gZGVsIGVycm9yIGFsZWF0b3JpbyBxdWUgc3Vwb25lbW9zIHF1ZSBzZSBkaXN0cmlidXllIGNvbW8gdW5hICRcbWF0aGNhbHtOfSgwLFxzaWdtYV4yKSQsIGRvbmRlICRcc2lnbWFeMiQgZXMgbGEgdmFyaWFuemEgcXVlIHN1ZWxlIHNlciBkZXNjb25vY2lkYS4NCg0KIyMgUmVzb2x1Y2nDs24gbWVkaWFudGUgbWF0cmljZXMNCg0KVXRpbGl6YW1vcyBlbCBtw6l0b2RvIGRlIG3DrW5pbW9zIGN1YWRyYWRvcyBxdWUgZXN0aW1hIGxvcyB2YWxvcmVzICRcaGF0e1xiZXRhfSQgaW50ZW50YW5kbyBtaW5pbWl6YXIgbG9zIGVycm9yZXMgJFxlcHNpbG9uJC4gQ29tbyBoZW1vcyB2aXN0byBlbiBjbGFzZSwgbGEgZsOzcm11bGEgcXVlIHNlIGRlZHVjZSBlczoNCg0KJCQgDQpcaGF0e1xiZXRhfSA9IChYXnRYKV57LTF9WF50WQ0KJCQNCmRvbmRlICRYJCBlcyB1bmEgY29sdW1uYSBkZSAxJ3MgY29uY2F0ZW5hZGEgY29uIGxhcyB2YXJpYWJsZXMgcXVlIHVzYW1vcyBwYXJhIHByZWRlY2lyLg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KeCA8LSBtb2RlbC5tYXRyaXgoIH4gQWNldGljICsgSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhcikNCmJldGFoYXQgPC0gc29sdmUoY3Jvc3Nwcm9kKHgsIHgpLCBjcm9zc3Byb2QoeCwgdGFzdGUpKQ0KYmV0YWhhdCA8LSBjKGJldGFoYXQpDQpiZXRhaGF0DQpgYGANClBvciB0YW50bywgYXByb3hpbWFtb3MgbGFzICRcYmV0YSQgbW9kZWxvIGxpbmVhbCBjb21wbGV0byBjb24gbG9zIHZhbG9yZXMgZGUgJFxoYXR7XGJldGF9XzAsXGRvdHMsXGhhdHtcYmV0YX1fMyQgY29uIGxvcyBzaWd1aWVudGVzIHZhbG9yZXM6DQoNCiQkDQpcaGF0e1xiZXRhfV8wPS0yOC44NzY3Njk2LFxxdWFkXGhhdHtcYmV0YX1fMT0wLjMyNzc0MTMsXHF1YWRcaGF0e1xiZXRhfV8yPTMuOTExODQxLFxxdWFkXGhhdHtcYmV0YX1fMz0xOS42NzA1NDM0DQokJA0KDQojIyBSZXNvbHVjacOzbiB1c2FuZG8gbGlicmVyaWFzIGRlIFINCg0KUG9kZW1vcyB1dGlsaXphciBsYSBmdW5jacOzbiAkbG0kLCB5YSBwcm9ncmFtYWRhIGVuIFIuIERlZmluaW1vcyBlbCBtb2RlbG8gY29tcGxldG8sIHkgY29tcHJvYmFtb3MgbGFzIGJldGFzOg0KDQokJA0KdGFzdGUgXHNpbSBBY2V0aWMgXCwgKyBcLCBIMlMgXCwgKyBcLCBMYWN0aWMsIFwsICBcLCBkYXRhID0gY2hlZGRhcg0KJCQNCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KbW9kZWwuYWxsLmxtIDwtIGxtKHRhc3RlIH4gLiwgZGF0YSA9IGNoZWRkYXIpDQoNCmZpbGFfY29lZiA8LSB2ZWN0b3IoKQ0KZGZfYW5vdmEgPC0gZGF0YS5mcmFtZSgiMSIgPSAxLCAiMiIgPSAyLCIzIiA9IDMsIjQiPTQsIHJvdy5uYW1lcyA9ICJDb2VmaWNpZW50ZXMiKQ0KY29sbmFtZXMoZGZfYW5vdmEpIDwtIGMoIkludGVyY2VwdCIsIkFjZXRpYyIsIkgyUyIsIkxhY3RpYyIpDQoNCmZvcihpIGluIDE6NCl7DQpmaWxhX2NvZWYgPC0gYyhmaWxhX2NvZWYsbW9kZWwuYWxsLmxtJGNvZWZmaWNpZW50c1tbaV1dKSAgDQp9DQoNCmRmX2Fub3ZhWzEsXSA8LSBmaWxhX2NvZWYNCmRmX2Fub3ZhDQoNCmBgYA0KDQoNCkVzdHVkaWVtb3MgcHJlbGltaW5hcm1lbnRlIHNpIGVzIHVuIG1vZGVsbyBsaW5lYWwgYWRlY3VhZG8sIHBhcmEgZWxsbyANCmNvbXByb2JhcmVtb3MgbGFzIGhpcMOzdGVzaXMgZXN0w6FuZGFyIGRlbCBtb2RlbG8gbGluZWFsIGRlIHJlZ3Jlc2nDs24gdXNhbmRvIGVsICoqdGVzdCBkZSBub3JtYWxpZGFkIFNoYXBpcm8tV2lsayoqLiBMYSBmdW5jacOzbiAkc2hhcGlyby50ZXN0JCBsZSBwYXNhbW9zIHBvciBwYXLDoW1ldHJvIGVsIHJlc2lkdW8vZXJyb3IgZGUgY2FkYSB1bmEgZGUgbGFzIG11ZXN0cmFzIHkgbm9zIGRldnVlbHZlIHVuICRwJC12YWxvci4NCg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLmFsbC5sbSkpDQpgYGANCk9ic2VydmFtb3MgcXVlIGVzdGFtb3MgZW4gbGEgaGlww7N0ZXNpcyBkZSBxdWUgZWwgZXJyb3IgbnVlc3RybyBtb2RlbG8gc2UgZGlzdHJpYnV5ZSBkZSBtYW5lcmEgbm9ybWFsLCB5YSBxdWUgZWwgcC12YWxvciBlcyAkMC44ODY1ID4gMC4wNSQuIA0KDQpPdHJvIGFzcGVjdG8gcXVlIGRlYmVtb3Mgc2FiZXIgZXMgc2kgbGEgbWVkaWEgZGUgbG9zIGVycm9yZXMgc2Vyw6EgbnVsYSBvIG5vLCBwYXJhIGVsbG8gdXNhbW9zIHVuYSBmdW5jacOzbiBpbXBsZW1lbnRhZGEgZW4gUiBxdWUgbm9zIGFmaXJtYSBxdWUgZW4gbnVlc3RybyBjYXNvIGVzdG8gZXMgYXPDrS4gUmVzcGVjdG8gYSBsb3MgZXJyb3JlcyB0ZW5lbW9zIHF1ZSBzYWJlciBxdWUgc2UgZGlzdHJpYnV5ZW4gY29uIHZhcmlhbnphIGNvbnN0YW50ZSwgcXVlIGRlIG1hbmVyYSBhbsOhbG9nYSBjb21wcm9iYW1vcywgdGVuaWVuZG8gcC12YWxvcmVzIGxvIHN1ZmljaWVudGVtZW50ZSBiYWpvcyBjb21vIHBhcmEgcmVjaGF6YXIgdmFyaWFuemEgbm8gY29uc3RhbnRlLg0KIERlIGlndWFsIG1hbmVyYSB0ZW5lbW9zIHF1ZSBubyBoYXkgYXV0b2NvcnJlbGFjacOzbiBlbiBlbCBtb2RlbG8gY29tcGxldG8uDQoNClVuYSB2ZXogaGVtb3MgY29uY2x1aWRvIHF1ZSBhdW5xdWUgZXN0YW1vcyBlbiBsYXMgaGlww7N0ZXNpcyBkZSByZWdyZXNpw7NuIGxpbmVhbA0KZWwgbW9kZWxvIGNvbXBsZXRvIGEgcGVzYXIgZGUgc2VyIGVsIG3DoXMgY29tcGxlam8gcHJvYmFibGVtZW50ZSBkYSByZXN1bHRhZG9zIA0Kc2ltaWxhcmVzIGEgb3RybyBtw6FzIHNpbXBsZS4NCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCmRmX3Jlc3VtZW4gPC0gdGlkeShtb2RlbC5hbGwubG0pDQpgYGANCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KZGZfcmVzdW1lbg0KYGBgDQoNClRyYXMgcmVhbGl6YXIgZWwgc3VtbWFyeSBkZWwgbW9kZWxvLCB1bmEgb2JzZXJ2YWNpw7NuIG11eSBpbXBvcnRhbnRlIHF1ZSBzYWNhbW9zIGVzIHF1ZSBlbCBwLXZhbG9yIGRlIEFjZXRpYyBlcyBtdXkgZ3JhbmRlICgwLjk0KSBwb3IgbG8gcXVlIG5vIHZhIGEgc2VyIHVuYSB2YXJpYWJsZSBzaWduaWZpY2F0aXZhIHkgcG9yIHRhbnRvIGNvbiBjYXNpIHRvZGEgc2VndXJpZGFkIG5vIHRpZW5lIGltcGFjdG8gcmVhbCBlbiBlbCBtb2RlbG8uDQoNClBvciBlbCBjb250cmFyaW8gZWwgcmVzdG8gZGUgdmFyaWFibGVzIHPDrSBzb24gc2lnbmlmaWNhdGl2YXMgcG9yIHRlbmVyIHAtdmFsb3IgaW5mZXJpb3IgYSAwLjUsIGRlc3RhY2FuZG8gTGFjdGljIHBvciB0ZW5lciB1biBiZXRhIG1heW9yIHF1ZSBIMlMsIGxvIHF1ZSBwcHVlZGUgaGFjZXJub3MgbGxlZ2FyIGEgcGVuc2FyIHF1ZSBjb2JyZSBtw6FzIGltcG9ydGFuY2lhIGVuIHVuIG1vZGVsbyBmaW5hbC4gIA0KDQojIyMjIENvcnJlbGFjaW9uZXMgeSB0YWJsYSBkZSByZXN1bHRhZG9zIGNvbiBlbCBlc3R1ZGlvIGRlIHN1cyBwLXZhbG9yZXMgIA0KDQpVc2Ftb3MgZWwgcGFxdWV0ZSAkR0dwbG90JCBkZSBSLCBlbCBjdWFsIG5vcyBwZXJtaXRlIHZpc3VhbGl6YXIgbGEgY29ycmVsYWNpw7NuIHkgZGlzcGVyc2nDs24gZW50cmUgbGFzIGRpc3RpbnRhcyB2YXJpYWJsZXMuDQoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9My41LCBmaWcud2lkdGg9NywgbWVzc2FnZT1GQUxTRX0NCmNvcnBsb3QgPC0gZ2dwYWlycyhjaGVkZGFyW3RyYWluLF0sIHByb2dyZXNzPUZBTFNFKQ0KY29ycGxvdCANCmBgYA0KDQpQZGVtb3MgYXByZWNpYXIgcXVlIGxhIHZhcmlhYmxlIGNvbiBtZW5vciBjb2VmZWNpZW50ZSBkZSBjb3JyZWxhY2nDs24gZGUgUGVhcnNvbiBlcyBBY2V0aWMsbWllbnRyYSBxdWUgZWwgcmVzdG8gZGUgdmFyaWFibGVzIHRpZW5lbiAgdW4gdmFsb3IgYmFzdGFudGUgbWF5b3IuIENhYmUgZGVzdGFjYXIgcXVlIHRvZG9zIHRpZW5lbiB1biBzaWdubyBwb3NpdGl2bywgbG8gcXVlIG5vcyBkaWNlIHF1ZSBlbiBnZW5lcmFsIGFsIGF1bWVudGFyIHVuYSBhdW1lbnRhIGxhIG90cmEuDQoNCg0KIyMgwr9UaWVuZSAqb3V0bGllcnMqIG51ZXN0cmEgbXVlc3RyYT8NCg0KUGFyYSBjb21wcm9iYXJsbyBiYXN0YSByZWFsaXphciBlbCAqKnRlc3QgZGUgQm9uZmVycm9uaSoqIHNvYnJlIG51ZXN0cm8gbW9kZWxvIGNvbXBsZXRvOg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Kb3V0bGllclRlc3QobW9kZWwuYWxsLmxtKQ0KYGBgDQoNCg0KQ29uY2x1aW1vcyBjb24gdW4gbml2ZWwgJFxhbHBoYSQgPSAwLjA1IHF1ZSBubyB0ZW5lbW9zIG5pbmfDum4gb3V0bGllciBlbiBudWVzdHJhLiBMbyBtw6FzIGNlcmNhbm8gYSB1biAqb3V0bGllciogcXVlIHRlbmVtb3MgZXMgbGEgb2JzZXJ2YWNpw7NuIG7Dum1lcm8gMTUsIHF1ZSB0aWVuZSB1biB2YWxvciAqKkJvbmZlcnJvbmkgcCoqIGRlIDAuMTc0NTMgKG5vIHNlIGFjZXJjYSBhIDAuMDUpLiBQb3IgdGFudG8sIG5vIHRlbmVtb3MgcmF6b25lcyBwb3IgbGFzIHF1ZSBlbGltaW5hciBhbGd1bmEgb2JzZXJ2YWNpw7NuIGludXN1YWwgZGUgbnVlc3RybyBjb25qdW50byBkZSBkYXRvcy4gDQoNCkVzdG8gc2UgcHVlZGUgY29tcHJvYmFyIGdyYWZpY2FtZW50ZSBhIHRyYXbDqXMgZGVsIHNpZ3VpZW50ZSBncsOhZmljbywgZWwgY3VhbCBtaWRlIGxhIGluZmx1ZW5jaWEgZGUgY2FkYSBvYnNlcnZhY2nDs24gc29icmUgY2FkYSB1bmEgZGUgbGFzIGJldGFzIGRlIG51ZXN0cm8gbW9kZWxvLiANCg0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0zLjZ9DQppbmZsdWVuY2VJbmRleFBsb3QobW9kZWwuYWxsLmxtKQ0KYGBgDQoNClZlbW9zIHF1ZSBsYSBxdWUgbcOhcyBpbmZsdXllIGVzIGxhIGFudGVzIG1lbmNpb25hZGEgb2JzZXJ2YWNpw7NuIDE1IHkgcG9yIHRhbnRvIGRlYmVyw61hbW9zIGNvbnNpZGVyYXIgc2kgZXMgb3V0bGllci4gSGVtb3MgY29tcHJvYmFkbyBxdWUgc3VjZWRlcsOtYSBhbCBlbGltaW5hciBlc2Egb2JzZXJ2YWNpw7NuIGRlIGxhIG11ZXN0cmEsIHkgc2kgYmllbiBtZWpvcmFiYSBhbGfDum4gcC12YWxvciBkZSBsYXMgaGlww7N0ZXNpcyBkZSByZWdyZXNpw7NuLCBlbiBvdHJvcyBsb3MgZW1wZW9yYWJhLCBhc8OtIHF1ZSBoZW1vcyBkZWNpZGlkbyBubyBlbGltaW5hcmxhIHkgZXNwZXJhcm5vcyBhIHZlciBlbCBjYXNvIGVuIGxhcyBzZWVkcyBxdWUgZXN0dWRpYXJlbW9zIGNvbiBtw6FzIGRldGFsbGVzIHNpIHNhbGUgZGUgbGEgbXVlc3RyYSBjb21vIG9ic2VydmFjacOzbiBpbmZsdXllbnRlLiANCg0KIyDCv0N1w6FsIGVzIGVsIG1lam9yIG1vZGVsbz8NCg0KQ29tbyBkaWNlIGVsICoqUHJpbmNpcGlvIGRlIGxhIE5hdmFqYSBkZSBPY2toYW0qKiwgYSBtZW51ZG8gbGEgZXhwbGljYWNpw7NuIG3DoXMgc2ltcGxlIGVzIGxhIGNvcnJlY3RhLiBRdWVyZW1vcyBzZWxlY2Npb25hciBwcmVkaWN0b3JlcyBxdWUgZXhwbGljYW4gbG9zIGRhdG9zIGRlIGxhIG1hbmVyYSBtw6FzIHNpbXBsZSBwb3NpYmxlLCBzaW4gZGlzbWludWlyIGxhIGNhbGlkYWQgZGUgbGFzIHByZWRpY2Npb25lcyBtdWNoby4NCg0KIyMjIFNlcGFyYWNpb24gZGVsIGRhdGFzZXQgZW4gY29uanVudG9zIGRlIGVudHJlbmFtaWVudG8geSB0ZXN0ICg3MC0zMCUpICANCg0KSGVtb3MgZXNjb2dpZG8gZGlzdGludGFzIHNlbWlsbGFzIHBhcmEgZXN0YXIgZW4gY29uZGljaW9uZXMgZGUgcmVhbGl6YXIgdW4gZXN0dWRpbyBtw6FzIGFtcGxpbywgZW4gbGEgZWxlY2Npw7NuIGRlIGxhcyBtaXNtYXMgc2UgaGEgaW50ZW50YWRvDQpldml0YXIgYXF1ZWxsYXMgcXVlIGdlbmVyYWJhbiBtdWVzdHJhcyBkZW1hc2lhZG8gc2ltaWxhcmVzLiBMYXMgc2VtaWxsYXMgdXNhZGFzIHNvbiAxLCAxMTAwIHkgNSBwb3N0ZXJpb3JtZW50ZSBzZSBpbnRyb2R1Y2lyw6FuIGRvcyBtw6FzIHBhcmEgYWZpbmFyIGVuIGVsIGPDoWxjdWxvIGRlIGVycm9yZXMuDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpzZXQuc2VlZCgxKSANCnRyYWluLjEgPC0gc2FtcGxlKGMoVFJVRSwgRkFMU0UpLCBzaXplID0gbnJvdyhjaGVkZGFyKSwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuNywgMC4zKSkNCnRlc3QuMSA8LSAoIXRyYWluLjEpDQpzdW0odGVzdC4xKQ0KbW9kZWwuYWxsMSA8LSBsbSh0YXN0ZSB+IC4sIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSkNCnNldC5zZWVkKDExMDApIA0KdHJhaW4uMiA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC4yIDwtICghdHJhaW4uMikNCnN1bSh0ZXN0LjIpDQpzdW0odGVzdC4xPT1UUlVFICYgdGVzdC4yPT1UUlVFKSNzb2xvIDEgcHJlc2VndWltb3MNCm1vZGVsLmFsbDIgPC0gbG0odGFzdGUgfiAuLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yLF0pDQpzZXQuc2VlZCg1KSANCnRyYWluLjMgPC0gc2FtcGxlKGMoVFJVRSwgRkFMU0UpLCBzaXplID0gbnJvdyhjaGVkZGFyKSwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuNywgMC4zKSkNCnRlc3QuMyA8LSAoIXRyYWluLjMpDQpzdW0odGVzdC4zKQ0Kc3VtKHRlc3QuMT09VFJVRSAmIHRlc3QuMz09VFJVRSkNCnN1bSh0ZXN0LjI9PVRSVUUgJiB0ZXN0LjM9PVRSVUUpDQptb2RlbC5hbGwzIDwtIGxtKHRhc3RlIH4gLiwgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMyxdKQ0KYGBgDQpDb25zaWRlcmVtb3MgbG9zIGNvbmp1bnRvcyBkZSBlbnRyZW5hbWllbnRvIHJlc3VsdGFudGVzIGRlIGxhcyBzZW1pbGxhczogKnRyYWluLjEqKHNlbWlsbGEgMSksICp0cmFpbi4yKihzZW1pbGxhIDExMDApLCAqdHJhaW4uMyooc2VtaWxsYSA1KS5WZWFhbW9zIHF1ZSBtb2RlbG9zIGRlYmVtb3MgY29uc2lkZXJhciBlbiBiYXNlIGEgbnVlc3Ryb3MgdHJhaW4uDQoNCiMjIyBNw6l0b2RvIEJhY2t3YXJkDQoNClBhcnRpbW9zIGRlbCBtb2RlbG8gY29tcGxldG8gZXN0dWRpYWRvIGVuIGxhIHNlY2Npw7NuIGFudGVyaW9yLCBlc28gc8OtLCBldmFsdWFkbyBlbiBudWVzdHJvcyByZXNwZWN0aXZvcyB0cmFpbiB5IGFwbGljYW1vcyBjb24gJFxhbHBoYSQgPSAwLjA1LCBlbCBtw6l0b2RvIGRlIEJhY2t3YXJkLCBxdWUgY29uc2lzdGUgZW4gZWxpbWluYXIgbGEgdmFyaWFibGUgcXVlICptZW5vcyBpbmZsdXlhKiBhIGxhIHByZWRpY2Npw7NuLiBQcmltZXJvIHJlYWxpemFtb3MgdW5hIGl0ZXJhY2nDs24gZXhwbMOtY2l0YSBkZWwgbcOpdG9kbyBzb2JyZSBsYSBwcmltZXJhIHNlbWlsbGEsIHkgcG9zdGVyaW9ybWVudGUgc2UgY29uc3RydXllbiBhIHRyYXbDqXMgZGUgIGxhIGxpYnJlcmlhICptaXhsbSogZGUgUi4gDQoNCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludH0NCiMgZHJvcDEobW9kZWwuYWxsLmxtLCB0ZXN0ID0gIkYiKVtbNl1dDQpmaWxhX3B2YWxvcmVzIDwtIGMoMC4zMzYyNywgMC4wNDMxOCwgMC4wMjM2NSApDQpkZl9wdmFsX2Ryb3BfcDEgPC0gZGF0YS5mcmFtZSgiMSIgPSAxLCAiMiIgPSAyLCIzIiA9IDMsIHJvdy5uYW1lcyA9ICJwLXZhbG9yIikNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gYygiQWNldGljIiwiSDJTIiwiTGFjdGljIikNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gZmlsYV9wdmFsb3Jlcw0KZGZfcHZhbF9kcm9wX3AxDQpgYGANCg0KRWxpbWluYW1vcyBBY2V0aWMgZGVsIG1vZGVsbyBkZWJpZG8gcXVlIHN1IHAtdmFsb3IgZXMgPjAuMDUuICANCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KbW9kZWwuYmFja3dhcmQgPC0gdXBkYXRlKG1vZGVsLmFsbC5sbSwgLiB+IC4gLSBBY2V0aWMpDQojIGRyb3AxKG1vZGVsLmJhY2t3YXJkLCB0ZXN0ID0gIkYiKVtbNl1dDQpmaWxhX3B2YWxvcmVzIDwtIGMoMC4wNTEyMiAsIDAuMDMyNzUpDQpkZl9wdmFsX2Ryb3BfcDIgPC0gZGF0YS5mcmFtZSgiMSIgPSAxLCAiMiIgPSAyLCByb3cubmFtZXMgPSAicC12YWxvciIpDQpjb2xuYW1lcyhkZl9wdmFsX2Ryb3BfcDIpIDwtIGMoIkgyUyIsIkxhY3RpYyIpDQpkZl9wdmFsX2Ryb3BfcDJbMSxdIDwtIGZpbGFfcHZhbG9yZXMNCmRmX3B2YWxfZHJvcF9wMg0KYGBgDQpSZXBldGltb3MgZWwgcHJvY2VzbyBjb24gbGEgdmFyaWFibGUgSDJTLCB5YSBxdWUgdGllbmUgdW4gcC12YWxvciBtYXlvciBxdWUgJFxhbHBoYSA9IDAuMDUkDQoNCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludH0NCm1vZGVsLmJhY2t3YXJkIDwtIHVwZGF0ZShtb2RlbC5iYWNrd2FyZCwgLiB+IC4gLSBIMlMpDQojZHJvcDEobW9kZWwuYmFja3dhcmQsIHRlc3QgPSAiRiIpDQpmaWxhX3B2YWxvcmVzIDwtIGMoMS4zODhlLTA1KQ0KZGZfcHZhbF9kcm9wX3AzIDwtIGRhdGEuZnJhbWUoIjEiID0gMSwgcm93Lm5hbWVzID0gInAtdmFsb3IiKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AzKSA8LSBjKCJMYWN0aWMiKQ0KZGZfcHZhbF9kcm9wX3AzWzEsXSA8LSBmaWxhX3B2YWxvcmVzDQpkZl9wdmFsX2Ryb3BfcDMNCmBgYA0KDQpFbCBwLXZhbG9yIGVzIG1lbm9yIHF1ZSAkXGFscGhhID0gMC4wNSQsIHBvciBsbyBxdWUgaGVtb3MgY29uY2x1aWRvLCB5YSBxdWUgbm8gdGVuZW1vcyBzdWZpY2llbnRlIGNlcnRlemEgcGFyYSBwb2RlciBlbGltaW5hciBvdHJhIHZhcmlhYmxlLlBvciB0YW50bywgdGVuZW1vcyBjb21vIHJlc3VsdGFkbyBxdWUgbGEgdmFyaWFibGUgcXVlIG1lam9yIGV4cGxpY2EgZWwgKnRhc3RlKiBlcyAqTGFjdGljKi4gTW9kZWxvIHJlc3VsdGFudGU6ICoqdGFzdGUgIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xLF0qKi4gIA0KDQpQb3Igb3RybyBsYWRvIGxvcyBtb2RlbG9zIGJhY2t3YXJkIHJlc3VsdGFudGVzIHBvciAqbWl4bG0qIHNvbjogIA0KDQoqKnRhc3RlICB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMixdKiogeSBwb3Igb3RybyBsYWRvICoqdGFzdGUgIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zLF0qKi4NCg0KIyMjIE3DqXRvZG8gRm9yd2FyZCANCg0KRWwgbcOpdG9kbyBGb3J3YXJkIGNvbnNpc3RlIGVuIGVtcGV6YXIgY29uIHVuIG1vZGVsbyBkZSB1bmEgdmFyaWFibGUgeSB2YW1vcyBhw7FhZGllbmRvIGxhcyBxdWUgbcOhcyBpbmZsdXlhbiwgZGVzYXJyb2xsYXJlbW9zIGVsIHByaW1lciBtb2RlbG8gZGUgZm9ybWEgZXhwbMOtY2l0YSB5IGVsIHJlc3RvIGxvcyBnZW5lcmFyZW1vcyBjb24gKm1peGxtKi4gIERlIGVzdGEgbWFuZXJhIHRlbmVtb3M6ICANCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KU0NPUEU8LSh+LitBY2V0aWMgKyBIMlMgKyBMYWN0aWMpDQptb2RlbC5mb3J3YXJkLmxtIDwtIGxtKHRhc3RlfjEsZGF0YT0gY2hlZGRhclt0cmFpbixdKQ0KI2FkZDEobW9kZWwuZm9yd2FyZC5sbSxzY29wZT1TQ09QRSx0ZXN0PSJGIilbWzZdXQ0KZmlsYV9wdmFsb3JlcyA8LSBjKDEuMjUxNzg2ZS0wMiwgMi4xMTU0NzNlLTA1LCAxLjM4NzkyM2UtMDUpDQpkZl9wdmFsX2Ryb3BfcDEgPC0gZGF0YS5mcmFtZSgiMSIgPSAxLCAiMiIgPSAyLCIzIiA9IDMsIHJvdy5uYW1lcyA9ICJwLXZhbG9yIikNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gYygiQWNldGljIiwiSDJTIiwiTGFjdGljIikNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gZmlsYV9wdmFsb3Jlcw0KZGZfcHZhbF9kcm9wX3AxDQpgYGANCkFjdHVhbGl6YW1vcyBhw7FhZGllbmRvIExhY3RpYyBwb3IgdGVuZXIgZWwgbWVub3IgcC12YWxvci4NCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludH0NCm1vZGVsLmZvcndhcmQubG0gPC0gdXBkYXRlKG1vZGVsLmZvcndhcmQubG0sIC5+LiArIExhY3RpYykNCiMgYWRkMShtb2RlbC5mb3J3YXJkLmxtLHNjb3BlPVNDT1BFLHRlc3Q9IkYiKVtbNl1dDQpmaWxhX3B2YWxvcmVzIDwtIGMoMC41MDM5ODc3NCAsMC4wNTEyMTcxMTUpDQpkZl9wdmFsX2Ryb3BfcDEgPC0gZGF0YS5mcmFtZSgiMSIgPSAxLCAiMiIgPSAyLCByb3cubmFtZXMgPSAicC12YWxvciIpDQpjb2xuYW1lcyhkZl9wdmFsX2Ryb3BfcDEpIDwtIGMoIkFjZXRpYyIsIkgyUyIpDQpkZl9wdmFsX2Ryb3BfcDFbMSxdIDwtIGZpbGFfcHZhbG9yZXMNCmRmX3B2YWxfZHJvcF9wMQ0KYGBgDQpDb24gbml2ZWwgZGUgc2lnbmlmaWNhY2nDs24gJFxhbHBoYSQgPSAwLjA1IGVzdGUgc2Vyw61hIG51ZXN0cm8gbW9kZWxvIGZpbmFsLiBNb2RlbG8gcmVzdWx0YW50ZSA9ICoqdGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSoqICANClBvciBvdHJvIGxhZG8gbG9zIG1vZGVsb3MgZm9yd2FyZCByZXN1bHRhbnRlcyBwb3IgKm1peGxtKiBzb246ICANCg0KKip0YXN0ZSAgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjIsXSoqIHkgcG9yIG90cm8gbGFkbyAqKnRhc3RlICB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMyxdKiouDQoNCiMjIENvbnN0cnVjY2nDs24gcG9yIGNyaXRlcmlvcw0KDQpFbiBlc3RhIHN1YnNlY2Npw7NuIHRyYXRhcmVtb3MgZGUgZW5jb250cmFyIHVuIGNhbmRpZGF0byBhIG1lam9yIG1vZGVsbywgY29uc3RydXllbmRvIG51ZXN0cm9zIG1vZGVsb3MgdXNhbmRvIGRpc3RpbnRvcyBlbmZvcXVlcy4gVHJhcyBhcGxpY2FyDQpsb3Mgc2lndWllbnRlcyBjcml0ZXJpb3MgYSBsYSBob3JhIGRlbCBkZXNhcnJvbGxvIGRlIG1vZGVsb3M6ICRSXjIkIGFqdXN0YWRvLCBDcCBkZSBNYWxsb3dzLCBDcml0ZXJpbyBkZSBJbmZvcm1hY2lvbiBkZSBCYXllcyAoQklDKSwgQ3JpdGVyaW8gZGUgSW5mb3JtYWNpb24gZGUgQWthaWtlIChBSUMpIGVsaWdpZW5kbyBlbCBxdWUgbm9zIGRlIHVuIG1lbm9yIG8gbWF5b3IgY29lZmljaWVudGUgc2Vnw7puIGVsIG3DqXRvZG8gKGxvcyBkZXNhcnJvbG9zIHNlIHB1ZWRlbiBlbmNvbnRyYXIgZW4gZWwgc2NyaXB0KSwgbGxlZ2Ftb3MgYSBsYXMgc2lndWllbnRlcyBjb25jbHVzaW9uZXM6ICANCnNvbG8gYXBhcmVjZSB1biBtb2RlbG8gbnVldm8gdXNhbmRvIGVsIGNyaXRlcmlvIGRlbCBlc3RhZMOtc3RpY28gJFJeMiQgcGFyYSBsYSBwcmltZXJhIHNlbWlsbGEsICoqdGFzdGUgIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xLF0qKi4gIA0KTm90YW1vcyBxdWUgbGEgY29tYmluYWNpw7NuIGRlIEgyUyArIEwgYXBhcmVjZSBlbiB0b2RvcyBudWVzdHJvcyBjb25qdW50b3MgZGUgZW50cmVuYW1pZW50byBlbiBhbGfDum4gbW9tZW50bywgZXMgY2FuZGlkYXRhIGEgc2VyIG51ZXN0cmEgbWVqb3IgZWxlY2Npw7NuLiAgDQoNCkNvbXBhcmFtb3MgbG9zIG1vZGVsb3Mgb2J0ZW5pZG9zIGhhc3RhIGFob3JhIGVuIHN1IHJlc3BlY3RpdmEgbXVlc3RyYSBkZSBlbnRyZW5hbWllbnRvIGNvbiBlbCBtb2RlbG8gY29tcGxldG8gZW4gZXNlIGNvbmp1bnRvIGRlIGVudHJlbmFtaWVudG8uDQoNCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KbW9kZWwuMSA8LSBsbSh0YXN0ZSB+IExhY3RpYywgIGRhdGE9Y2hlZGRhclt0cmFpbi4xLF0pDQptb2RlbC4xY3JpdCA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YT1jaGVkZGFyW3RyYWluLjEsXSkNCm1vZGVsLjIgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsICBkYXRhPWNoZWRkYXJbdHJhaW4uMixdKQ0KbW9kZWwuMyA8LSBsbSh0YXN0ZSB+IEgyUyArTGFjdGljLCAgZGF0YT1jaGVkZGFyW3RyYWluLjMsXSkNCiMgYW5vdmEobW9kZWwuMSxtb2RlbC5hbGwxKVtbNl1dDQojIGFub3ZhKG1vZGVsLjFjcml0LG1vZGVsLmFsbDEpW1s2XV0NCiMgYW5vdmEobW9kZWwuMixtb2RlbC5hbGwyKQ0KIyBhbm92YShtb2RlbC4zLG1vZGVsLmFsbDMpW1s2XV0NCmZpbGFfcHZhbG9yZXMgPC0gYygwLjA5ODIxNDUzLA0KICAgICAgICAgICAgICAgICAgIDAuMzM2MjY4OSwNCiAgICAgICAgICAgICAgICAgICAwLjk1NTExMjMsDQogICAgICAgICAgICAgICAgICAgMC41NTUxMjkyKQ0KYW5vdmEobW9kZWwuMSxtb2RlbC5hbGwxKSAgICAgICAgICAgICAgICANCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IDEsICIyIiA9IDIsIjMiID0gMywiNCI9IDQsIHJvdy5uYW1lcyA9ICJwLXZhbG9yIikNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gYygidHJhaW4xOiBMIHZzIENvbXBsZXRvIiwidHJhaW4xOiBIMlMgKyBMIHZzIENvbXBsZXRvIiwidHJhaW4yOiBIMlMgKyBMIHZzIENvbXBsZXRvIiwgInRyYWluMTogSDJTKyBMIHZzIENvbXBsZXRvIikNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gZmlsYV9wdmFsb3Jlcw0KZGZfcHZhbF9kcm9wX3AxICAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgIA0KYGBgDQoNCkNvbiBlc3RvcyBwLXZhbG9yZXMgcG9kZW1vcyBkZWNpciBxdWUgY29uIHVuIG5pdmVsIGRlIHNpZ25pZmljYWNpw7NuICRcYWxwaGEkIG5pbmfDum4gbW9kZWxvIGVzIG5vdGFibGVtZW50ZSBkaWZlcmVudGUgZGUgc3UgY29udHJhcGFydGUgc2Fsdm8gZW4gZWwgY2FzbyBkZSBsb3MgbW9kZWxvcyByZXN1bHRhbnRlcyBlbiAqdHJhaW4yKiBlc3RvIHB1ZWRlIHNlciBwb3IgbGEgY2FudGlkYWQgZGUgb2JzZXJ2YWNpb25lcyBpbmZsdXllbnRlcyBwcmVzZW50ZXMgZW4gbGEgbXVlc3RyYSwgbG8gdHJhdGFyZW1vcyBlbiBsYSBzaWd1aWVudGUgc2VjY2nDs24uICANCg0KIyBEaWFnbm9zdGljbzogQ29tcHJvYmFjaW9uZXMgZGUgaGlwb3Rlc2lzLCBvdXRsaWVycyB5IG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMNCg0KRW4gZXN0YSBzZWNjacOzbiBlc3R1ZGlhcmVtb3Mgc2kgbnVlc3Ryb3MgbW9kZWxvcyBjdW1wbGVuIGxhcyBjb25kaWNpb25lcw0KbmVjZXNhcmlhcyBkZSB1biBtb2RlbG8gZGUgcmVncmVzacOzbiBsaW5lYWwuICANCg0KTnVlc3RybyBlbmZvcXVlIGNvbnNpc3RpcsOhIGVuIHVuIGFuw6FsaXNpcyBncsOhZmljbywgYWNvbXBhw7FhZG8gZGUgdGVzdHMNCmVzdGFkw61zdGljb3MgZW4gbG9zIGNhc29zIGVuIGxvcyBxdWUgc2UgYXByZWNpZSB1bmEgZGlzY3JlcGFuY2lhIG5vdGFibGUuDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQphdHRhY2goY2hlZGRhcikNCmBgYA0KDQojIyDCv1NvbiBudWVzdHJvcyAqbW9kZWxvcyosIG1vZGVsb3MgZGUgcmVncmVzacOzbiBsaW5lYWw/OiBDb21wcm9iYWNpw7NuIGRlIGhpcMOzdGVzaXMuDQoNCkVuIGxhIHNlY2Npw7NuIDMgc2UgdG9tYSB1biBlbmZvcXVlICpuYcOvdmUqIGEgbGEgaG9yYSBkZSBjb25zdHJ1aXIgbG9zIG1vZGVsb3MsDQp5YSBxdWUgbm8gaGVtb3MgZXN0dWRpYWRvIHNpIGhheSBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzLCBwb2Ryw61hbW9zIHRlbmVyIHVuYQ0KbXVlc3RyYSBxdWUgbm8gZXMgbGEgYWRlY3VhZGEgcGFyYSBlbCBlc3R1ZGlvIGRlIG51ZXN0cm9zIGRhdG9zLiAgDQoNClVuIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbCBkZWJlIHNhdGlzZmFjZXIgbGFzIHNpZ3VpZW50ZXMgaGlww7N0ZXNpcyBjb24gbml2ZWwgDQpkZSBzaWduaWZpY2FjacOzbiAkXGFscGhhJCBhZGVjdWFkbzoNCg0KMS4gTG9zIGVycm9yZXMgXChcZXBzaWxvbl97aX1cKSB0aWVuZW4gZGlzdHJpYnVjacOzbiBub3JtYWwuICANCjIuIExvcyBlcnJvcmVzIFwoXGVwc2lsb25fe2l9XCkgdGllbmVuIG1lZGlhIGNlcm8uICANCjMuIExvcyBlcnJvcmVzIFwoXGVwc2lsb25fe2l9XCkgdGllbmVuIHZhcmlhbnphIGNvbnN0YW50ZS4gIA0KNC4gTG9zIGVycm9yZXMgXChcZXBzaWxvbl97aX1cKSBubyBlc3TDoW4gY29ycmVsYWNpb25hZG9zLiAgDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludH0NCmFsZmFuIDwtIDAuMDUNCmZpbGFfbGluZWFsaWRhZCA8LSBjKHJvdW5kKHJlc2V0dGVzdChtb2RlbC4xLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4xLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChyZXNldHRlc3QobW9kZWwuMWNyaXQsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjEsXSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHJlc2V0dGVzdChtb2RlbC4yLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4yLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChyZXNldHRlc3QobW9kZWwuMywgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMyxdKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgYWxmYW4sIlJlc2V0dGVzdCIpDQpmaWxhX25vcm1hbGlkYWQgPC0gYyhyb3VuZChzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMSkpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMWNyaXQpKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgcm91bmQoc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjIpKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgcm91bmQoc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjMpKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgYWxmYW4sICJUZXN0IFNoYXBpcm8gV2lsayIpDQpmaWxhX21lZGlhTyA8LSBjKHQudGVzdChyZXNpZChtb2RlbC4xKSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlLA0KICAgICAgICAgICAgICAgICB0LnRlc3QocmVzaWQobW9kZWwuMWNyaXQpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUsDQogICAgICAgICAgICAgICAgIHQudGVzdChyZXNpZChtb2RlbC4yKSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlLA0KICAgICAgICAgICAgICAgICB0LnRlc3QocmVzaWQobW9kZWwuMyksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZSwNCiAgICAgICAgICAgICAgICAgYWxmYW4sICJ0LXRlc3QiKQ0KZmlsYV92YXJfY3RlIDwtIGMocm91bmQobmN2VGVzdChtb2RlbC4xKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgcm91bmQobmN2VGVzdChtb2RlbC4xY3JpdCkkcCwzKSwNCiAgICAgICAgICAgICAgICAgIHJvdW5kKG5jdlRlc3QobW9kZWwuMikkcCwzKSwNCiAgICAgICAgICAgICAgICAgIHJvdW5kKG5jdlRlc3QobW9kZWwuMykkcCwzKSwNCiAgICAgICAgICAgICAgICAgIGFsZmFuLCAiVGVzdCBuY3YiKQ0KICAgICAgICAgICAgICAgICAgDQogICAgICAgICAgICAgICAgICANCmZpbGFfY29yciA8LSBjKGR1cmJpbldhdHNvblRlc3QobW9kZWwuMSkkcCwNCiAgICAgICAgICAgICAgIGR1cmJpbldhdHNvblRlc3QobW9kZWwuMWNyaXQpJHAsDQogICAgICAgICAgICAgICBkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjIpJHAsDQogICAgICAgICAgICAgICBkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjMpJHAsDQogICAgICAgICAgICAgICBhbGZhbiwiVGVzdCBkZSBEdXJiaW4tV2F0c29uIikNCiANCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IHJlcCgwLDUpLCIyIiA9IHJlcCgwLDUpLCIzIiA9IHJlcCgwLDUpLCI0Ij0gcmVwKDAsNSksICI1Ij0gcmVwKDAsNSksICI2IiA9IHJlcCgwLDUpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPWMoIkxpbmVhbGlkYWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vcm1hbGlkYWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk1lZGlhID0gMCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVmFyaWFuemEgY29uc3RhbnRlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDb3JyZWxhY2nDs24iKSkNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gICAgYygidHJhaW4xOiBMIiwidHJhaW4xOiBIMlMgKyBMIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidHJhaW4yOiBIMlMgKyBMIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidHJhaW4zOiBIMlMgKyBMIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTml2ZWwgZGUgc2lnaW5pZmljYWNpw7NuIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVGVzdCB1dGlsaXphZG8iKQ0KDQpkZl9wdmFsX2Ryb3BfcDFbMSxdIDwtIGZpbGFfbGluZWFsaWRhZA0KZGZfcHZhbF9kcm9wX3AxWzIsXSA8LSBmaWxhX25vcm1hbGlkYWQNCmRmX3B2YWxfZHJvcF9wMVszLF0gPC0gZmlsYV9tZWRpYU8NCmRmX3B2YWxfZHJvcF9wMVs0LF0gPC0gZmlsYV92YXJfY3RlDQpkZl9wdmFsX2Ryb3BfcDFbNSxdIDwtIGZpbGFfY29ycg0KYGBgDQoNCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KZGZfcHZhbF9kcm9wX3AxDQpgYGANCg0KDQpQb2RlbW9zIG9ic2VydmFyIHF1ZSBzZSB2ZXJpZmljYW4gYSBuaXZlbCBkZSBzaWduaWZpY2FjacOzbiAkXGFscGhhJCA9IDAuMDUgc2UgdmVyaWZpY2FuIHRvZGFzIGxhcyBoaXDDs3Rlc2lzIGRlIG1vZGVsbyBkZSByZWdyZXNpw7NuIGxpbmVhbC4gRW4gbGFzIHNpZ3VpZW50ZXMgZ3LDoWZpY2FzIHBvZGVtb3Mgb2JzZXJ2YXIgY29tbyBsb3MgcmVzaWR1b3MgZGUgbG9zIG1vZGVsb3MgKip0YXN0ZSB+IEgyUyArIEwqKiBkZSBsb3MgY29uanVudG9zICp0cmFpbjIqIHkgKnRyYWluMyogc2UgY29tcG9ydGFuIG1lam9yIHF1ZSBjdWFscXVpZXJhIGRlIGxvcyBtb2RlbG9zIHByb3B1ZXN0b3MgZW4gbGEgbXVlc3RyYSAqdHJhaW4xKg0KDQpgYGB7ciBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTMsIGZpZy53aWR0aD02fQ0KcGFyKG1mcm93PWMoMSwyKSkNCnFxbm9ybShyZXNpZChtb2RlbC4xKSkNCnFxbGluZShyZXNpZChtb2RlbC4xKSkNCg0KcXFub3JtKHJlc2lkKG1vZGVsLjFjcml0KSkNCnFxbGluZShyZXNpZChtb2RlbC4xY3JpdCkpDQoNCmBgYA0KYGBge3IgZWNobz1GQUxTRSwgZmlnLmhlaWdodD0zLCBmaWcud2lkdGg9Nn0NCnBhcihtZnJvdz1jKDEsMikpDQpxcW5vcm0ocmVzaWQobW9kZWwuMikpDQpxcWxpbmUocmVzaWQobW9kZWwuMikpDQoNCnFxbm9ybShyZXNpZChtb2RlbC4zKSkNCnFxbGluZShyZXNpZChtb2RlbC4zKSkNCg0KYGBgDQoNCg0KUG9zdGVyaW9ybWVudGUsIHJlYWxpemFtb3MgdW4gZXN0dWRpbyBkZSBsYSBjb2xpbmVhbGlkYWQuIFBhcmEgZWxsbywgb2JzZXJ2YW1vcyBxdWUgZWwgbW9kZWxvICoqdGFzdGUgfiBMYWN0aWMgLCBkYXRhPWNoZWRkYXJbdHJhaW4uMSxdKiogc29sbyB0aWVuZSB1biBwcmVkaWN0b3IgbHVlZ28gbm8gaGF5IHByZXNlbnRlIG5pbmfDum4gdGlwbyBjb2xpbmVhbGlkYWQuDQoNCmBgYHtyIGVjaG89RkFMU0UsIHJlbmRlcj1sZW1vbl9wcmludH0NCiMgdmlmKG1vZGVsLjEpIGRpamltb3MgcXVlIGVsIGRlIGxhY3RpYyBubyBwb3JxdWUgc3VjZWRlIGVzdG8gbm8gaGF5IGNvbGluIHBvciBzb2xvIDEgdmFyDQojIHZpZihtb2RlbC4xY3JpdCkNCiMgdmlmKG1vZGVsLjIpDQojIHZpZihtb2RlbC4zKSAjIGxvcyB2YWxvcmVzIGRlIFZJRiBubyBpbmRpY2FuIGNvbGluZWFsaWRhZCBncmF2ZQ0KDQoNCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IHJlcCgwLDQpLCIyIiA9IHJlcCgwLDQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID1jKCJ0cmFpbjE6IEwiLCJ0cmFpbjE6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFpbjI6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFpbjM6IEgyUyArIEwiKSkNCg0KZmlsYV9jMSA8LSBjKCJTb2xvIHRpZW5lIHVuIHByZWRpY3RvciIsIlNvbG8gdGllbmUgdW4gcHJlZGljdG9yIikNCmZpbGFfYzIgPC0gYyh2aWYobW9kZWwuMWNyaXQpW1sxXV0sdmlmKG1vZGVsLjFjcml0KVtbMl1dKQ0KZmlsYV9jMyA8LSBjKHZpZihtb2RlbC4yKVtbMV1dLHZpZihtb2RlbC4yKVtbMl1dKQ0KZmlsYV9jNCA8LSBjKHZpZihtb2RlbC4zKVtbMV1dLHZpZihtb2RlbC4zKVtbMl1dKQ0KDQpkZl9wdmFsX2Ryb3BfcDFbMSxdIDwtIGZpbGFfYzENCmRmX3B2YWxfZHJvcF9wMVsyLF0gPC0gZmlsYV9jMg0KZGZfcHZhbF9kcm9wX3AxWzMsXSA8LSBmaWxhX2MzDQpkZl9wdmFsX2Ryb3BfcDFbNCxdIDwtIGZpbGFfYzQNCg0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSBjKCJIMlMiLCJMYWN0aWMiKQ0KZGZfcHZhbF9kcm9wX3AxDQoNCmBgYA0KDQpOdWVzdHJvcyB2YWxvcmVzIHNvbiBtdXkgYnVlbm9zLCBlbnRlbmRpZW5kbyBwb3IgYnVlbm8gVklGIDwgMTAsIHBvciBsbyB0YW50byBubyB0ZW5lbmVtb3MgcXVlIHByZW9jdXBhcm5vcyBkZSB1bmEgY29saW5lYWxpZGFkIGdyYXZlIGVudHJlIGxhcyB2YXJpYWJsZXMuDQoNCg0KIyMgRXN0dWRpbyBkZSBvdXRsaWVycw0KDQpBIGZpbiBkZSBvYnRlbmVyIGRpc3RpbnRvcyBwdW50b3MgZGUgdmlzdGEgdXRpbGl6YXJlbW9zIGRvcyBtw6l0b2RvcywgdW4gdmFsb3IgZGUgQm9uZmVycm9uaSBlbiB1biBlc3RhZMOtc3RpY28gJHRfezEtXGZyYWN7XGFscGhhfXsybn07bi1wLTF9JCB5IGxhIGZ1bmNpw7NuICpvdXRsaWVyVGVzdCogcXVlIHV0aWxpemEgcC12YWxvcmVzIGRlIEJvbmZlcnJvbmkgb2J0ZW5pZG9zIGEgdHJhdsOpcyBkZSB0LXRlc3RzLiAgDQoNCkVuIGxvcyBjdWF0cm8gbW9kZWxvcyB5IGJham8gbG9zIGRvcyBjcml0ZXJpb3Mgbm8gc2Ugb2J0aWVuZSBuaW5ndW5hIG9ic2VydmFjacOzbiBxdWUgc2UgcHVlZGEgYWNlcHRhciBjb21vICpvdXRsaWVyKiBhIG5pdmVsIGRlIHNpZ25pZmljYWNpw7NuICRcYWxwaGEkID0gMC4wNQ0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0Kc2lnbmkgPC0gMC4wNQ0KDQpuMTwtbnJvdyhjaGVkZGFyW3RyYWluLjEsXSkNCnAxIDwtbnJvdyhzdW1tYXJ5KG1vZGVsLjEpJGNvZWYpDQoNCg0KbjFjcml0PC1ucm93KGNoZWRkYXJbdHJhaW4uMSxdKQ0KcDFjcml0IDwtbnJvdyhzdW1tYXJ5KG1vZGVsLjFjcml0KSRjb2VmKQ0KDQpuMjwtbnJvdyhjaGVkZGFyW3RyYWluLjIsXSkNCnAyIDwtbnJvdyhzdW1tYXJ5KG1vZGVsLjIpJGNvZWYpDQoNCm4zPC1ucm93KGNoZWRkYXJbdHJhaW4uMyxdKQ0KcDMgPC1ucm93KHN1bW1hcnkobW9kZWwuMykkY29lZikNCg0KQkNWMSA8LSBxdCgxIC0gc2lnbmkgLyAoMiAqIG4xKSwgbjEtcDEtMSkgDQpCQ1YxY3JpdCA8LSBxdCgxIC0gc2lnbmkgLyAoMiAqIG4xY3JpdCksIG4xY3JpdC1wMWNyaXQtMSkgDQpCQ1YyIDwtIHF0KDEgLSBzaWduaSAvICgyICogbjIpLCBuMi1wMi0xKSANCkJDVjMgPC0gcXQoMSAtIHNpZ25pIC8gKDIgKiBuMyksIG4zLXAzLTEpIA0KDQpzdW0oYWJzKHJzdHVkZW50KG1vZGVsLjEpKSA+IEJDVjEpDQpzdW0oYWJzKHJzdHVkZW50KG1vZGVsLjFjcml0KSkgPiBCQ1YxY3JpdCkNCnN1bShhYnMocnN0dWRlbnQobW9kZWwuMikpID4gQkNWMikNCnN1bShhYnMocnN0dWRlbnQobW9kZWwuMykpID4gQkNWMykNCg0KDQpvdXRsaWVyVGVzdChtb2RlbC4xKQ0Kb3V0bGllclRlc3QobW9kZWwuMWNyaXQpI05BPw0Kb3V0bGllclRlc3QobW9kZWwuMikgIyBubyBoYXkgZW4gbmluZ3VubyBkZSBsb3MgZG9zIG1vZGVsb3MgcGxhbnRlYWRvcw0Kb3V0bGllclRlc3QobW9kZWwuMykNCg0KYGBgDQojIyBFc3R1ZGlvIGRlIG9ic2VydmFjaW9uZXMgSW5mbHV5ZW50ZXMNCg0KQWwgaWd1YWwgcXVlIGVuIGxhIGFudGVyaW9yIHNlY2Npw7NuIGEgZmluIGRlIHBvZGVyIGVuY29udHJhciBlbCBjcml0ZXJpbyBxdWUgbWVqb3Igc2UgYWp1c3RlIGEgbnVlc3RybyBtb2RlbG8sIGVuIGVsIHF1ZSBoYXkgcXVlIHRlbmVyIGVuIGN1ZW50YSBxdWUgZXMgdW5hIG11ZXN0cmEgZGUgdGFtYcOxbyByZWR1Y2lkbywgdXRpbGl6YXJlbW9zIHZhcmlvcyBjcml0ZXJpb3MsIGFkZW3DoXMgZGUgZGlzdGludGFzIHTDqWNuaWNhcyBncsOhZmljYXMuIExvcyBjcml0ZXJpb3MgdXNhZG9zIHNlcsOhbjogIA0KMS5Dcml0ZXJpbyAxOiB2YWxvcmVzIGxldmVyYWdlIChoaWkpIG1heW9yZXMgcXVlICRcZnJhY3sycH17bn0kLiAgDQoyLkNyaXRlcmlvIDI6IHZhbG9yZXMgfERGRklUU3wgc29uIG1heW9yZXMgcXVlICQyIFxjZG90IFxzcXJ0e1xmcmFjezJwfXtufX0kLiAgDQoNCjMuQ3JpdGVyaW8gMzogdmFsb3JlcyB8REZCRVRBU3wgbWF5b3JlcyBxdWUgJDIgXGNkb3QgXHNxcnR7XGZyYWN7MnB9e259fSQuICANCg0KNC5Dcml0ZXJpbyA0OiAqSW5mbHVlbmNlUGxvdCouDQoNCkVuIGxhIHNpZ3VpZW50ZSB0YWJsYSBvYnNlcnZhbW9zIGxhcyBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIG9idGVuaWRhcyBwb3IgY2FkYSBjcml0ZXJpby4NCg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KDQpkZl9wdmFsX2Ryb3BfcDEgPC0gZGF0YS5mcmFtZSgiMSIgPSByZXAoMCw0KSwiMiIgPSByZXAoMCw0KSwiMyIgPSByZXAoMCw0KSwiNCIgPSByZXAoMCw0KSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcyA9YygidHJhaW4xOiBMIiwidHJhaW4xOiBIMlMgKyBMIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidHJhaW4yOiBIMlMgKyBMIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidHJhaW4zOiBIMlMgKyBMIikpDQoNCmZpbGFfYzEgPC0gYygiMSw1LDE2LDIzLDI0LDI2IiwgIjEsMTIsMjQiLCIxLDMsNSw4LDksMTIsMTMsMTQsMTYsMTksMjMsMjQsMjcsMjgsMzAiLCIxLDEyLDI0IikNCmZpbGFfYzIgPC0gYygiMjMiLCAiMTIiLCAiMSwzLDgsOSwxMSwxMiwxMywxNCwxOSwyMywyNCwyNiwyNywyOCwzMCIsIjEsOCwxMiwyMyIpDQpmaWxhX2MzIDwtIGMoIjYiLCJOaW5ndW5vIiAsICIxLDMsNCw3LDgsOSwxMSwxMiwxNiwxNywyMCwyOSwzMCIsIjEsNiw3LDgsMTUiKQ0KZmlsYV9jNCA8LSBjKCJOaW5ndW5vIiwiTmluZ3VubyIsIjEsNCw1LDcsMTIsMTQsMTYsMTcsMTksMjMsMjcsMjkiLCIxLDcsMTUsMTksMjQiKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSBjKCJDcml0ZXJpbyAxIiwiQ3JpdGVyaW8gMiIsIkNyaXRlcmlvIDMiLCJDcml0ZXJpbyA0IikNCg0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX2MxDQpkZl9wdmFsX2Ryb3BfcDFbMixdIDwtIGZpbGFfYzINCmRmX3B2YWxfZHJvcF9wMVszLF0gPC0gZmlsYV9jMw0KZGZfcHZhbF9kcm9wX3AxWzQsXSA8LSBmaWxhX2M0DQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KDQpUb21hbW9zIGxhIGRlY2lzacOzbiBkZSBlbGVnaXIgbG9zIGVsZW1lbnRvcyBxdWUgc2UgcmVwaXRhbiBlbiB2YXJpb3MgeWEgcXVlIHNpIGVsaW1pbsOhc2Vtb3MgbG9zIGRlbCBjcml0ZXJpbyAzIGVsIHJlc3VsdGFkbyBzZXLDrWEgZGVtYXNpYWRvIHBlcXVlw7FvIHBhcmEgc2VyIGFwdG8gcGFyYSBsYSByZWdyZXNpw7NuIGxpbmVhbC4gTnVlc3RybyBjcml0ZXJpbyBhIHNlZ3VpciBlcyBxdWUgZXN0w6luIGVuIGFsIG1lbm9zIGRvcyBjcml0ZXJpb3MgIGRlIGxvcyByZXN0YW50ZXMuDQoNCmBgYHtyIGVjaG89RkFMU0V9DQoNCnBhcihtZnJvdz1jKDIsMikpDQpwMSA8LSBpbmZsdWVuY2VQbG90KG1vZGVsLjEpDQpwb3NfaW5mbHV5ZW50ZXNfMSA8LSBjKDEsMTIsMjQpDQoNCnAyIDwtaW5mbHVlbmNlUGxvdChtb2RlbC4xY3JpdCkNCnBvc19pbmZsdXllbnRlc18xY3JpdCA8LSBjKDEsOCwxMiwyMykNCg0KcDMgPC1pbmZsdWVuY2VQbG90KG1vZGVsLjIpDQpwb3NfaW5mbHV5ZW50ZXNfMiA8LSBjKDEsNiw3LDgsMTUpDQoNCg0KcDQgPC1pbmZsdWVuY2VQbG90KG1vZGVsLjMpDQpwb3NfaW5mbHV5ZW50ZXNfMyA8LSBjKDEsNywxNSwxOSwyNCkNCg0KYGBgDQoNCkVzdGFzIG9ic2VydmFjaW9uZXMgc29uIGxhcyBwcmVzZW50ZXMgZW4gbGEgY3VhcnRhIGNvbHVtbmEgZGUgbGEgdGFibGEgeSBlbiBnZW5lcmFsIHNvbiBlbiBsYXMgcHJpbWVyYXMgZW4gbGFzIHF1ZSBub3MgZmlqZW1vcyBhIGxhIGhvcmEgZGUgdmVyIHNpIGxhcyB0b21hbW9zIGNvbW8gaW5mbHV5ZW50ZXMgbyBuby4NCg0KQmFqbyBudWVzdHJvIGNyaXRlcmlvIHF1ZWRhcsOtYW4gY29tbyBwb3NpYmxlcyBpbmZsdXllbnRlcyBsYXMgc2lndWllbnRlcyBvYnNlcnZhY2lvbmVzOg0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQpkZl9wdmFsX2Ryb3BfcDEgPC0gZGF0YS5mcmFtZSgiMSIgPXJlcCgwLDQpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93Lm5hbWVzID1jKCJ0cmFpbjE6IEwiLCJ0cmFpbjE6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFpbjI6IEgyUyArIEwiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJ0cmFpbjM6IEgyUyArIEwiKSkNCg0KZmlsYV9jMSA8LSBjKCIxLDEyIikNCmZpbGFfYzIgPC0gYygiMSwxMiwyMyIpDQpmaWxhX2MzIDwtIGMoIjIsNiIpDQpmaWxhX2M0IDwtIGMoIk5vIHNlIHJlcGl0ZSBuaW5ndW5vIikNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gYygiT2JzZXJ2YWNpb25lcyBpbmZsdXllbnRlcyIpDQoNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gZmlsYV9jMQ0KZGZfcHZhbF9kcm9wX3AxWzIsXSA8LSBmaWxhX2MyDQpkZl9wdmFsX2Ryb3BfcDFbMyxdIDwtIGZpbGFfYzMNCmRmX3B2YWxfZHJvcF9wMVs0LF0gPC0gZmlsYV9jNA0KZGZfcHZhbF9kcm9wX3AxDQpgYGANCg0KDQpBaG9yYSBlcyBjdWFuZG8gdGVuZW1vcyBxdWUgZGV0ZXJtaW5hciBzaSB2YW4gYSBzZXIgaW5mbHV5ZW50ZXMgbyBubywgZXN0byBsbyB2ZXJlbW9zIGNvbXBhcmFuZG8gbG9zIG1vZGVsb3MgY29uIGxhcyBtdWVzdHJhcyBkZSBlbnRyZW5hbWllbnRvIHNpbiBlbGltaW5hciBpbmZsdXllbnRlcyB5IGNvbiBsYXMgbXVlc3RyYXMgbW9kaWZpY2FkYXMsIHkgZXZhbHVhciBzaSBtZWpvcmFuIG8gZW1wZW9yYW4gbG9zIHAtdmFsb3JlcyBkZSBsYXMgaGlww7N0ZXNpcyBkZSBsb3MgbW9kZWxvcyBkZSByZWdyZXNpw7NuLg0KDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KcG9zXzE8LWMoVFJVRSxyZXAoRkFMU0UsMTApLFRSVUUscmVwKEZBTFNFLDE4KSkNCnRyYWluLjFpbmY8LXRyYWluLjEmIXBvc18xDQptb2RlbC4xaW5mPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjFpbmYsXSkNCmBgYA0KIyMjIHRhc3RlIH4gICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xLF0gdnMgdGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjFpbmYsXQ0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KDQpmaWxhX2xpbmVhbGlkYWQgPC0gYyhyb3VuZChyZXNldHRlc3QobW9kZWwuMSwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMSxdKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgcm91bmQocmVzZXR0ZXN0KG1vZGVsLjFpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjFpbmYsXSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgICJSZXNldHRlc3QiKQ0KDQoNCmZpbGFfbm9ybWFsaWRhZCA8LSBjKHJvdW5kKHNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xKSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xY3JpdCkpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICAiVGVzdCBTaGFwaXJvIFdpbGsiKQ0KZmlsYV9tZWRpYU8gPC0gYyh0LnRlc3QocmVzaWQobW9kZWwuMSksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZSwNCiAgICAgICAgICAgICAgICAgdC50ZXN0KHJlc2lkKG1vZGVsLjFpbmYpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUsDQogICAgICAgICAgICAgICAgICJ0LXRlc3QiKQ0KZmlsYV92YXJfY3RlIDwtIGMocm91bmQobmN2VGVzdChtb2RlbC4xKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgcm91bmQobmN2VGVzdChtb2RlbC4xaW5mKSRwLDMpLA0KICAgICAgICAgICAgICAgICAgIlRlc3QgbmN2IikNCiAgICAgICAgICAgICAgICAgIA0KICAgICAgICAgICAgICAgICAgDQpmaWxhX2NvcnIgPC0gYyhkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjEpJHAsDQogICAgICAgICAgICAgICBkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjFpbmYpJHAsDQogICAgICAgICAgICAgICAiVGVzdCBkZSBEdXJiaW4tV2F0c29uIikNCiANCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IHJlcCgwLDUpLCIyIiA9IHJlcCgwLDUpLCIzIiA9IHJlcCgwLDUpLHJvdy5uYW1lcyA9YygiTGluZWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vcm1hbGlkYWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNZWRpYSA9IDAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJWYXJpYW56YSBjb25zdGFudGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDb3JyZWxhY2nDs24iKSkNCg0KDQpjb2xuYW1lcyhkZl9wdmFsX2Ryb3BfcDEpIDwtICAgIGMoInRyYWluMTogTCIsInRyYWluMTogTCwgc2luIGluZmx1eWVudGVzIiwgIlRlc3QgdXRpbGl6YWRvIikNCg0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX2xpbmVhbGlkYWQNCmRmX3B2YWxfZHJvcF9wMVsyLF0gPC0gZmlsYV9ub3JtYWxpZGFkDQpkZl9wdmFsX2Ryb3BfcDFbMyxdIDwtIGZpbGFfbWVkaWFPDQpkZl9wdmFsX2Ryb3BfcDFbNCxdIDwtIGZpbGFfdmFyX2N0ZQ0KZGZfcHZhbF9kcm9wX3AxWzUsXSA8LSBmaWxhX2NvcnINCmRmX3B2YWxfZHJvcF9wMQ0KYGBgDQpOdWVzdHJhcyBoaXDDs3Rlc2lzIGRlbCBtb2RlbG8gbGluZWFsIHNlIHZlbiBub3RhYmxlbWVudGUgbWVqb3JhZGFzLCB0ZW5lbW9zIHVuYSBkaXN0cmlidWNpw7NuIG3DoXMgcGFyZWNpZGEgYSB1bmEgbm9ybWFsLCBtZWpvciBkaXN0cmlidWlkYSBlbiB0b3JubyBhIHVuYSBsaW5lYWwuICANClJlYWxpemFtb3MgdW4gcGVxdWXDsW8gaW50ZXJjYW1iaW8gZW4gZWwgcXVlIG51ZXN0cmEgdmFyaWFuemEgcGFyZWNlIG1lbm9zIGNvbnN0YW50ZSBwZXJvIHNlIG1hbnRpZW5lIHBvciBlbmNpbWEgZGUgdG9kb3MgbG9zIG5pdmVsZXMgZGUgc2lnbmlmaWNhY2nDs24gaGFiaXR1YWxlcy4gIA0KVG9tYW1vcyBsYSBkZWNpc2nDs24gZGUgYWN0dWFsaXphciAqY2hlZGRhclt0cmFpbi4xLF0qIGNvbiAgKmNoZWRkYXJbdHJhaW5pbmYuMSxdKiwgcXVlIGVzIGxhIHZlcnNpw7NuIHNpbiBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzLg0KIyMjIHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xLF0gdnMgdGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjFjcml0aW5mLF0NCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQp0cmFpbi4xYXV4PC10cmFpbi4xDQp0cmFpbi4xPC10cmFpbi4xaW5mDQptb2RlbC4xPC1tb2RlbC4xaW5mDQpgYGANCg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCnBvc18xY3JpdDwtYyhUUlVFLHJlcChGQUxTRSwxMCksVFJVRSxyZXAoRkFMU0UsMTApLFRSVUUscmVwKEZBTFNFLDcpKQ0KDQp0cmFpbi4xY3JpdGluZjwtdHJhaW4uMWF1eCYhcG9zXzFjcml0DQptb2RlbC4xY3JpdGluZjwtIGxtKHRhc3RlIH5IMlMrTGFjdGljICwgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMWNyaXRpbmYsXSkNCmBgYA0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQoNCmZpbGFfbGluZWFsaWRhZCA8LSBjKHJvdW5kKHJlc2V0dGVzdChtb2RlbC4xY3JpdCwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMSxdKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgcm91bmQocmVzZXR0ZXN0KG1vZGVsLjFjcml0aW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4xY3JpdGluZixdKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgIlJlc2V0dGVzdCIpDQoNCg0KZmlsYV9ub3JtYWxpZGFkIDwtIGMocm91bmQoc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjFjcml0KSkkcC52YWx1ZSwzKSwNCiAgICAgICAgICAgICAgICAgICAgIHJvdW5kKHNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xY3JpdGluZikpJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICAiVGVzdCBTaGFwaXJvIFdpbGsiKQ0KZmlsYV9tZWRpYU8gPC0gYyh0LnRlc3QocmVzaWQobW9kZWwuMWNyaXQpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUsDQogICAgICAgICAgICAgICAgIHQudGVzdChyZXNpZChtb2RlbC4xY3JpdGluZiksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZSwNCiAgICAgICAgICAgICAgICAgInQtdGVzdCIpDQpmaWxhX3Zhcl9jdGUgPC0gYyhyb3VuZChuY3ZUZXN0KG1vZGVsLjFjcml0KSRwLDMpLA0KICAgICAgICAgICAgICAgICAgcm91bmQobmN2VGVzdChtb2RlbC4xY3JpdGluZikkcCwzKSwNCiAgICAgICAgICAgICAgICAgICJUZXN0IG5jdiIpDQogICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgIA0KZmlsYV9jb3JyIDwtIGMoZHVyYmluV2F0c29uVGVzdChtb2RlbC4xY3JpdCkkcCwNCiAgICAgICAgICAgICAgIGR1cmJpbldhdHNvblRlc3QobW9kZWwuMWNyaXRpbmYpJHAsDQogICAgICAgICAgICAgICAiVGVzdCBkZSBEdXJiaW4tV2F0c29uIikNCiANCmRmX3B2YWxfZHJvcF9wMSA8LSBkYXRhLmZyYW1lKCIxIiA9IHJlcCgwLDUpLCIyIiA9IHJlcCgwLDUpLCIzIiA9IHJlcCgwLDUpLHJvdy5uYW1lcyA9YygiTGluZWFsaWRhZCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIk5vcm1hbGlkYWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJNZWRpYSA9IDAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJWYXJpYW56YSBjb25zdGFudGUiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDb3JyZWxhY2nDs24iKSkNCg0KDQpjb2xuYW1lcyhkZl9wdmFsX2Ryb3BfcDEpIDwtICAgIGMoInRyYWluMTogSDJTICsgTCIsInRyYWluMTogSDJTICsgTCwgc2luIGluZmx1eWVudGVzIiwgIlRlc3QgdXRpbGl6YWRvIikNCg0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBmaWxhX2xpbmVhbGlkYWQNCmRmX3B2YWxfZHJvcF9wMVsyLF0gPC0gZmlsYV9ub3JtYWxpZGFkDQpkZl9wdmFsX2Ryb3BfcDFbMyxdIDwtIGZpbGFfbWVkaWFPDQpkZl9wdmFsX2Ryb3BfcDFbNCxdIDwtIGZpbGFfdmFyX2N0ZQ0KZGZfcHZhbF9kcm9wX3AxWzUsXSA8LSBmaWxhX2NvcnINCg0KDQoNCg0KZGZfcHZhbF9kcm9wX3AxDQoNCg0KYGBgDQpFc3RlIGVzIHVuIGNhc28gdW4gdGFudG8gcGFydGljdWxhciwgdGVuZW1vcyB1bm9zIGRhdG9zIHBlcmZlY3RhbWVudGUgZGlzdHJpYnVpZG9zLCBwZXJvIHlhIGxvIGVzdGFiYW4gYW50ZXMgcHJhY3RpY2FtZW50ZS4gQSBjYW1iaW8gZGUgZXNvIHBlcmRlbW9zIHVuIGNpZXJ0byBncmFkbyBkZSBsaW5lYWxpZGFkIHF1ZSBoYXkgcXVlIHRlbmVyIGVuIGN1ZW50YSwgZW4gZXN0ZSBjYXNvIG5vIGhheSB1bmEgZGlmZXJlbmNpYSB0YW4gbm90YWJsZSBjb24gZWwgbW9kZWxvIGNvbW8gZW4gcXVlIHNvbG8gaW5jb3Jwb3JhYmEgYSBMYWN0aWMuICANCg0KVG9tYW1vcyBsYSBkZWNpc2nDs24gZGUgYWN0dWFsaXphciAqY2hlZGRhclt0cmFpbi4xY3JpdCxdKiBjb24gICpjaGVkZGFyW3RyYWluLjFjcml0aW5mLF0qLCBxdWUgZXMgbGEgdmVyc2nDs24gc2luIG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMuDQoNCiMjIyB0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMixdIHZzIHRhc3RlIH4gSDJTICsgTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yaW5mLF0NCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQp0cmFpbi4xY3JpdDwtdHJhaW4uMWNyaXRpbmYNCm1vZGVsLjFjcml0PC0gbW9kZWwuMWNyaXRpbmYNCmBgYA0KDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQpwb3NfMjwtYyhyZXAoRkFMU0UsNSksVFJVRSxyZXAoRkFMU0UsMjQpKQ0KDQp0cmFpbi4yaW5mPC10cmFpbi4yJiFwb3NfMg0KbW9kZWwuMmluZjwtIGxtKHRhc3RlIH4gSDJTK0xhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMmluZixdKQ0KYGBgDQoNCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQoNCmZpbGFfbGluZWFsaWRhZCA8LSBjKHJvdW5kKHJlc2V0dGVzdChtb2RlbC4yLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4yLF0pJHAudmFsdWUsMyksDQogICAgICAgICAgICAgICAgICAgICByb3VuZChyZXNldHRlc3QobW9kZWwuMmluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMmluZixdKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgIlJlc2V0dGVzdCIpDQoNCg0KZmlsYV9ub3JtYWxpZGFkIDwtIGMocm91bmQoc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjIpKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgcm91bmQoc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjJpbmYpKSRwLnZhbHVlLDMpLA0KICAgICAgICAgICAgICAgICAgICAgIlRlc3QgU2hhcGlybyBXaWxrIikNCmZpbGFfbWVkaWFPIDwtIGModC50ZXN0KHJlc2lkKG1vZGVsLjIpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUsDQogICAgICAgICAgICAgICAgIHQudGVzdChyZXNpZChtb2RlbC4yaW5mKSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlLA0KICAgICAgICAgICAgICAgICAidC10ZXN0IikNCmZpbGFfdmFyX2N0ZSA8LSBjKHJvdW5kKG5jdlRlc3QobW9kZWwuMikkcCwzKSwNCiAgICAgICAgICAgICAgICAgIHJvdW5kKG5jdlRlc3QobW9kZWwuMmluZikkcCwzKSwNCiAgICAgICAgICAgICAgICAgICJUZXN0IG5jdiIpDQogICAgICAgICAgICAgICAgICANCiAgICAgICAgICAgICAgICAgIA0KZmlsYV9jb3JyIDwtIGMoZHVyYmluV2F0c29uVGVzdChtb2RlbC4yKSRwLA0KICAgICAgICAgICAgICAgZHVyYmluV2F0c29uVGVzdChtb2RlbC4yaW5mKSRwLA0KICAgICAgICAgICAgICAgIlRlc3QgZGUgRHVyYmluLVdhdHNvbiIpDQogDQpkZl9wdmFsX2Ryb3BfcDEgPC0gZGF0YS5mcmFtZSgiMSIgPSByZXAoMCw1KSwiMiIgPSByZXAoMCw1KSwiMyIgPSByZXAoMCw1KSxyb3cubmFtZXMgPWMoIkxpbmVhbGlkYWQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJOb3JtYWxpZGFkIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiTWVkaWEgPSAwIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVmFyaWFuemEgY29uc3RhbnRlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ29ycmVsYWNpw7NuIikpDQoNCg0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSAgICBjKCJ0cmFpbjI6IEgyUyArIEwiLCJ0cmFpbjI6IEgyUyArIEwsIHNpbiBpbmZsdXllbnRlcyIsICJUZXN0IHV0aWxpemFkbyIpDQoNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gZmlsYV9saW5lYWxpZGFkDQpkZl9wdmFsX2Ryb3BfcDFbMixdIDwtIGZpbGFfbm9ybWFsaWRhZA0KZGZfcHZhbF9kcm9wX3AxWzMsXSA8LSBmaWxhX21lZGlhTw0KZGZfcHZhbF9kcm9wX3AxWzQsXSA8LSBmaWxhX3Zhcl9jdGUNCmRmX3B2YWxfZHJvcF9wMVs1LF0gPC0gZmlsYV9jb3JyDQoNCg0KZGZfcHZhbF9kcm9wX3AxDQpgYGANCkVuIGNpZXJ0YSBtYW5lcmEgZXMgbm90YWJsZSBxdWUgYWwgZWxpbWluYXIgbnVlc3RyYXMgaW5mbHV5ZW50ZXMgeSBlbiB1biAqZGF0YXNldCogdGFuIHBlcXVlw7FvIG5vIGdlbmVyZSBhIHBlbmFzIGRpZmVyZW5jaWEsIGVuIHRvZG8gY2FzbyBub3MgbWVqb3JhIHRvZGFzIGxhcyBoaXDDs3Rlc2lzIGRlbCBtb2RlbG8gbGluZWFsLCBzZSBwdWVkZSBhZmlybWFyIHF1ZSBlcyB1biBtb2RlbG8gbWVqb3IgcGFyYSB0cmFiYWphciBzb2JyZSBlbCBhIHByaW9yaS4gIA0KDQpUb21hbW9zIGxhIGRlY2lzacOzbiBkZSBhY3R1YWxpemFyICpjaGVkZGFyW3RyYWluLjIsXSogY29uICAqY2hlZGRhclt0cmFpbmluZi4yLF0qLCBxdWUgZXMgbGEgdmVyc2nDs24gc2luIG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMuDQpgYGB7ciBpbmNsdWRlPUZBTFNFfQ0KdHJhaW4uMjwtdHJhaW4uMmluZg0KbW9kZWwuMjwtbW9kZWwuMmluZg0KYGBgDQojIyMgdGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjMsXSAgDQpFbiBlc3RlIG1vZGVsbywgYmFqbyBlbCBjcml0ZXJpbyBkZSBlbGVjY2nDs24gZGUgb2JzZXJ2YWNpb25lcyBpbmZsdXllbnRlcyBxdWUgZWxlZ2ltb3MgcGFyYSB0cmF0YXIgbnVlc3Ryb3MgZGF0b3MsIGVzdGUgbW9kZWxvIG5vIHByZXNlbnRhYmEgbmluZ3VuYSBvYnNlcnZhY2nDs24gaW5mbHV5ZW50ZSwgcG9yIGxvIHF1ZSBzZSBtYW50aWVuZSBjb21vIGVzdMOhLg0KDQoNCiMgRXJyb3JlcyBkZSBUZXN0LiBDb21wYXJhY2lvbiBkZSBNb2RlbG9zDQoNCg0KDQpOdWVzdHJvIHJhem9uYW1pZW50byBwYXJhIGVuZnJlbnRhcm5vcyBhIGVzdGEgc2VjY2nDs24gZXMgZWwgc2lndWllbnRlLCBub3MgaGFuIHNhbGlkbyBkb3MgbW9kZWxvcyBwb3NpYmxlcyB5IHBhcmEgY29tcHJlbmRlciBjdWFsIHNlIGFqdXN0YSBtZWpvciBhIG51ZXN0cm9zIGRhdG9zIHZhbW9zIGEgZXNjb2dlciBjaW5jbyBzZWVkcyB5IGV2YWx1YXIgY2FkYSBtb2RlbG8gZW4gdG9kYXMgZWxsYXMsIGEgZmluIGRlIGhhY2VyIHVuYSBtZWRpYSBkZSBsb3MgZXJyb3Jlcy4NCg0KUGFyYSBlc3RvIHVzYW1vcyBsYXMgdHJlcyBzZWVkcyBxdWUgaGVtb3MgdXRpbGl6YWRvIGEgbG8gbGFyZ28gZGVsIGRvY3VtZW50bywgeSBsZSBhw7FhZGltb3Mgb3RyYXMgZG9zIGVsZWdpZGFzIGFsIGF6YXIuIE7Ds3Rlc2UgcXVlIGV2YWx1YXIgZW4gbGEgcHJpbWVyYSBzZWVkIHlhIGVzdMOhIGhlY2hvLCBwdWVzIGVuIGVzdGEgbm9zIHNhbMOtYW4gbG9zIGRvcyBtb2RlbG9zIGEgY29uc2lkZXJhci4gQWRlbcOhcyBlbiBsYXMgc2VlZHMgZG9zIHkgdHJlcyB5YSBlc3TDoSBoZWNobyBwYXJhIGVsIG1vZGVsbyBjb24gSDJTICsgTGFjdGljLCBwZXJvIGhheSBxdWUgcmVwZXRpciBlbCBwcm9jZXNvIHBhcmEgZWwgb3RybyBtb2RlbG8uDQpEZSBlc3RhIG1hbmVyYSByZWFsaXphbW9zIGxvcyBtaXNtb3MgY8OhbGN1bG9zIHF1ZSBsb3MgcmVhbGl6YWRvcyBlbiBsYSBwYXJ0ZSBkZSBkaWFnbsOzc3RpY28sIHNvYnJlIGxhcyBjb21iaW5hY2lvbmVzLiBFc3RvIGVzLCBub3MgYXNlZ3VyYW1vcyBxdWUgY2FkYSBtb2RlbG8gY29uIHRvZG9zIGxvcyB0cmFpbiBjdW1wbGEgbGFzIGhpcMOzdGVzaXMgZGUgbm9ybWFsaWRhZCwgbWVkaWEgZGUgZXJyb3JlcyBudWxhLCBob21vY2VkYXN0aWNpZGFkLCBsaW5lYWxpZGFkIHkgYXV0b2NvcnJlbGFjacOzbi4gRGVzcHXDqXMgZGUgZXN0byBub3MgcGxhbnRlYW1vcyBzaSB0aWVuZSBkYXRvcyBpbmZsdXllbnRlcyBzZWfDum4gbGFzIGZ1bmNpb25lcyBhZGVjdWFkYXMsIGVuIGNhc28gZGUgdGVuZXJsb3MgcmVhbGl6YW1vcyB1bmEgcHJ1ZWJhLiBsb3MgcXVpdGFtb3MgZGVsIHRyYWluIHkgdmVtb3Mgc2kgc2UgbWVqb3JhIGVsIHAtdmFsb3IgZGUgYWxndW5hIGRlIGxhcyBjYXJhY3RlcsOtc3RpY2FzIGFudGVyaW9yZXMgeSBlbiBiYXNlIGEgZXNvIGRlY2lkaW1vcyBzaSBlbGltaW5hbW9zIGxhcyBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIG8gbm8uIA0KDQpDb24gdG9kbyBlc28gcmVhbGl6YWRvIGxsZWdhbW9zIGEgbGEgc2lndWllbnRlIHRhYmxhLCBxdWUgbm9zIHBlcm1pdGUgYXN1bWlyIGNvbW8gdmFsaWRvcyB0b2RvcyBsb3MgY2Fzb3MgeSBjYWxjdWxhciBzdXMgZXJyb3Jlcy4NCg0KDQoNCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQojIElOVFJPRFVDSVIgU0VDQ0lPTiA1DQojIENPTVBMRVRBUiBUQUJMQSBPVVRMSUVSUw0KIyBDUkVPIFFVRSBURU5JQSBRVUUgUE9ORVIgSE9NT0VTVCBBUlJJQkENCiMgSlVTVE8gRU4gRUwgU1VNTUFSWSBERSBMQSBTRUNDSU9OIDYgQ1JFTyBRVUUgRUwgREFUQSBOTyBERUJFUklBIFNFUiBDSEVEREFSDQoNCiMgVmFtb3MgYSBjb25zaWRlcmFyIG90cmFzIGRvcyBzZW1pbGxhcyBwYXJhIGV2YWx1YXIgbG9zIG1vZGVsb3MgeSBlbGVnaXIgZWwgbWVqb3IuDQojIExhcyB0b21hbW9zIGRlIGZvcm1hIHF1ZSBubyBjb2luY2lkYW4gZW4gbGEgbWVkaWRhIGRlIGxvIHBvc2libGUgbG9zIHRlc3RzIGRlIGxhcyBkaXN0aW50YXMgcGFydGljaW9uZXMuDQojIERpdmlkaW1vcyBlbCBjb25qdW50byB0b3RhbCBwYXJhIGxhcyBkb3Mgc2VtaWxsYXMgbnVldmFzLg0KDQpzZXQuc2VlZCgoMjIzNCkpDQp0cmFpbi40IDwtIHNhbXBsZShjKFRSVUUsIEZBTFNFKSwgc2l6ZSA9IG5yb3coY2hlZGRhciksIHJlcGxhY2UgPSBUUlVFLCBwcm9iID0gYygwLjcsIDAuMykpDQp0ZXN0LjQgPC0gKCF0cmFpbi40KQ0Kc3VtKHRlc3QuNCkNCnN1bSh0ZXN0LjE9PVRSVUUgJiB0ZXN0LjQ9PVRSVUUpDQpzdW0odGVzdC4yPT1UUlVFICYgdGVzdC40PT1UUlVFKQ0Kc3VtKHRlc3QuMz09VFJVRSAmIHRlc3QuND09VFJVRSkNCg0KDQpzZXQuc2VlZCgoMTMxKSkNCnRyYWluLjUgPC0gc2FtcGxlKGMoVFJVRSwgRkFMU0UpLCBzaXplID0gbnJvdyhjaGVkZGFyKSwgcmVwbGFjZSA9IFRSVUUsIHByb2IgPSBjKDAuNywgMC4zKSkNCnRlc3QuNSA8LSAoIXRyYWluLjUpDQpzdW0odGVzdC41KQ0Kc3VtKHRlc3QuMT09VFJVRSAmIHRlc3QuNT09VFJVRSkNCnN1bSh0ZXN0LjI9PVRSVUUgJiB0ZXN0LjU9PVRSVUUpDQpzdW0odGVzdC4zPT1UUlVFICYgdGVzdC41PT1UUlVFKQ0Kc3VtKHRlc3QuND09VFJVRSAmIHRlc3QuNT09VFJVRSkNCg0KdHJhaW4uMWggPC0gdHJhaW4uMWNyaXQNCnRyYWluLjJoIDwtIHRyYWluLjINCnRyYWluLjNoIDwtIHRyYWluLjMNCnRyYWluLjRoIDwtIHRyYWluLjQNCnRyYWluLjVoIDwtIHRyYWluLjUNCg0KIyBSZWNhbGN1bGFtb3MgdHJhaW4uMiBwb3JxdWUgZnVlIG1vZGlmaWNhZG8NCnNldC5zZWVkKDExMDApDQp0cmFpbi4yIDwtIHNhbXBsZShjKFRSVUUsIEZBTFNFKSwgc2l6ZSA9IG5yb3coY2hlZGRhciksIHJlcGxhY2UgPSBUUlVFLCBwcm9iID0gYygwLjcsIDAuMykpDQoNCg0KDQoNCiMgVmVhbXNvIHNpIHBvZGVtb3MgZWxpbWluYXIgcG9zaWJsZXMgaW5mbHV5ZW50ZXMgZW4gbG9zIG1vZGVsb3MgcmVzdGFudGVzDQoNCm1oMSA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMWgsXSkgIyBjb21wcm9iYWRvcyBzdXB1ZXN0b3MNCm1oMiA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMmgsXSkgIyBjb21wcm9iYWRvcyBzdXB1ZXN0b3MNCm1oMyA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uM2gsXSkgIyBjb21wcm9iYWRvcyBzdXB1ZXN0b3MNCm1oNCA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uNGgsXSkNCm1oNSA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uNWgsXSkNCg0KbTEgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSkgIyBjb21wcm9iYWRvcyBzdXB1ZXN0b3MNCm0yIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yLF0pDQptMyA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMyxdKQ0KbTQgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjQsXSkNCm01IDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi41LF0pDQoNCg0KIyBBbCBpZ3VhbCBxdWUgaGljaW1vcyBlbiA0IGNvbXByb2JhbW9zIHNpIHJldGlyYW5kbyBvdXRsaWVycyB5IG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMgbWVqb3JhbiBsYXMgaGlwb3Rlc2lzLg0KIyAgVW5pY2FtZW50ZSBjb25zaWRlcmFyZW1vcyBvYnNlcnZhY2lvbmVzIG9idGVuaWRhcyB0YW50byBwb3Igb3V0bGllclRlc3QoKSBjb21vIHBvciBpbmZsdWVuY2VQbG90KCkuDQoNCiMgbWg0DQpvdXRsaWVyVGVzdChtaDQpDQppbmZsdWVuY2VQbG90KG1oNCkgIyA2LDEyLDE1LDI0DQpwb3M0aCA8LSBjKHJlcChGQUxTRSw1KSxUUlVFLHJlcChGQUxTRSw1KSxUUlVFLHJlcChGQUxTRSwyKSxUUlVFLHJlcChGQUxTRSw4KSxUUlVFLHJlcChGQUxTRSw2KSkNCg0KdHJhaW4uNGluZiA8LSB0cmFpbi40aCYhcG9zNGgNCm1oNGluZiA8LSBsbSh0YXN0ZSB+IEgyUytMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjRpbmYsXSkNCg0KbmN2VGVzdChtaDQpDQpuY3ZUZXN0KG1oNGluZikgIyBtZWpvcmEgTVVDSE8NCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG1oNCkpDQpzaGFwaXJvLnRlc3QocmVzaWQobWg0aW5mKSkgIyBtZWpvcmENCg0KZHVyYmluV2F0c29uVGVzdChtaDQpDQpkdXJiaW5XYXRzb25UZXN0KG1oNGluZikgIyBtZWpvcmENCg0KcmVzZXR0ZXN0KG1oNCwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNGluZixdKSANCnJlc2V0dGVzdChtaDRpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjRpbmYsXSkgIyBlbXBlb3JhIHBlcm8gZXMgYWNlcHRhYmxlDQoNCiMgUmVkZWZpbmltb3MgZWxpbWluYW5kbyBwb3M0aCBwb3Igc2VyIHRhbnRhIGxhIG1lam9yYSBlbiBob21vY2VkYXN0aWNpZGFkIHF1ZSBjb21wZW5zYSBsYSBsaW5lYWxpZGFkDQp0cmFpbi40aCA8LSB0cmFpbi40aW5mDQptaDQgPC0gbWg0aW5mDQoNCg0KIyBtaDUNCm91dGxpZXJUZXN0KG1oNSkNCmluZmx1ZW5jZVBsb3QobWg1KSAjIDYsNyw4LDEyLDE1DQpwb3M1aCA8LSBjKHJlcChGQUxTRSw1KSxUUlVFLFRSVUUsVFJVRSxyZXAoRkFMU0UsMyksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsMTUpKQ0KDQp0cmFpbi41aW5mIDwtIHRyYWluLjVoJiFwb3M1aA0KbWg1aW5mIDwtIGxtKHRhc3RlIH4gSDJTK0xhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uNWluZixdKQ0KDQpuY3ZUZXN0KG1oNSkNCm5jdlRlc3QobWg1aW5mKSAjIG1lam9yYSANCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG1oNSkpDQpzaGFwaXJvLnRlc3QocmVzaWQobWg1aW5mKSkgIyBlbXBlb3JhDQoNCmR1cmJpbldhdHNvblRlc3QobWg1KQ0KZHVyYmluV2F0c29uVGVzdChtaDVpbmYpICMgYSB2ZWNlcyBubyBzZSBjdW1wbGUgbGEgaGlwb3Rlc2lzIG51bGEgZGUgbm8gYXV0b2NvcnJlbGFjaW9uDQoNCnJlc2V0dGVzdChtaDUsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjVpbmYsXSkgDQpyZXNldHRlc3QobWg1aW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi41aW5mLF0pICMgZW1wZW9yYQ0KDQojIERlY2lkaW1vcyBubyBhY3R1YWxpemFyIGVsIG1vZGVsbyBwdWVzIG5vIHNpZW1wcmUgc2UgcmVjaGF6YSBsYSBjb3JyZWxhY2lvbiB5IGVtcGVvcmFuIG90cm9zIHAtdmFsb3Jlcy4NCg0KDQojIG0yDQpvdXRsaWVyVGVzdChtMikNCmluZmx1ZW5jZVBsb3QobTIpICMgMSwxMiwxNSwxOCwyNA0KcG9zMiA8LSBjKFRSVUUscmVwKEZBTFNFLDEwKSxUUlVFLHJlcChGQUxTRSwyKSxUUlVFLHJlcChGQUxTRSwyKSxUUlVFLHJlcChGQUxTRSw1KSxUUlVFLHJlcChGQUxTRSw2KSkNCg0KdHJhaW4uMmluZiA8LSB0cmFpbi4yJiFwb3MyDQptMmluZiA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMmluZixdKQ0KDQpuY3ZUZXN0KG0yKQ0KbmN2VGVzdChtMmluZikgIyBlbXBlb3JhIGxpZ2VyYW1lbnRlDQoNCnNoYXBpcm8udGVzdChyZXNpZChtMikpDQpzaGFwaXJvLnRlc3QocmVzaWQobTJpbmYpKSAjIGVtcGVvcmEgbGlnZXJhbWVudGUNCg0KZHVyYmluV2F0c29uVGVzdChtMikNCmR1cmJpbldhdHNvblRlc3QobTJpbmYpICMgZW1wZW9yYSBiYXN0YW50ZQ0KDQpyZXNldHRlc3QobTIsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjJpbmYsXSkgDQpyZXNldHRlc3QobTJpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjJpbmYsXSkgIyBtZWpvcmENCg0KIyBEZWNpY2ltb3Mgbm8gcmVkZWZpbmlybG8sIHlhIHF1ZSBlbXBlb3JhIGVuIG11Y2hhcyB5IG1lam9yYSBiYXN0YW50ZSBlbiB1bmENCg0KDQojIG0zDQpvdXRsaWVyVGVzdChtMykNCmluZmx1ZW5jZVBsb3QobTMpICMgMSwxNSwxOSwyNA0KcG9zMyA8LSBjKFRSVUUscmVwKEZBTFNFLDEzKSxUUlVFLHJlcChGQUxTRSwzKSxUUlVFLHJlcChGQUxTRSw0KSxUUlVFLHJlcChGQUxTRSw2KSkNCg0KdHJhaW4uM2luZiA8LSB0cmFpbi4zJiFwb3MzDQptM2luZiA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uM2luZixdKQ0KDQpuY3ZUZXN0KG0zKQ0KbmN2VGVzdChtM2luZikgIyBtZWpvcmEgcG9jbw0KDQpzaGFwaXJvLnRlc3QocmVzaWQobTMpKQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG0zaW5mKSkgIyBtZWpvcmENCg0KZHVyYmluV2F0c29uVGVzdChtMykNCmR1cmJpbldhdHNvblRlc3QobTNpbmYpICMgZW1wZW9yYQ0KDQpyZXNldHRlc3QobTMsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjNpbmYsXSkgDQpyZXNldHRlc3QobTNpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjNpbmYsXSkgIyBlbXBlb3JhIGNhc2kgbG8gcGllcmRlDQoNCiMgRGVjaWRpbW9zIG5vIHJlZGVmaW5pcmxvIHBvciBlc3RhciBhbCBib3JkZSBlbiB1biBjcml0ZXJpbyB5IG5vIG1lam9yYXIgbXVjaG8gZW4gb3Ryb3MNCg0KDQojIG00DQpvdXRsaWVyVGVzdChtNCkNCmluZmx1ZW5jZVBsb3QobTQpICMgNiwxMiwxNSwyMCwyNA0KcG9zNCA8LSBjKHJlcChGQUxTRSw1KSxUUlVFLHJlcChGQUxTRSw1KSxUUlVFLHJlcChGQUxTRSwyKSxUUlVFLHJlcChGQUxTRSw0KSxUUlVFLHJlcChGQUxTRSwzKSxUUlVFLHJlcChGQUxTRSw2KSkNCg0KdHJhaW4uNGluZiA8LSB0cmFpbi40JiFwb3M0DQptNGluZiA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uNGluZixdKQ0KDQpuY3ZUZXN0KG00KQ0KbmN2VGVzdChtNGluZikgIyBlbXBlb3JhIGJhc3RhbnRlDQoNCnNoYXBpcm8udGVzdChyZXNpZChtNCkpDQpzaGFwaXJvLnRlc3QocmVzaWQobTRpbmYpKSAjIGVtcGVvcmENCg0KZHVyYmluV2F0c29uVGVzdChtNCkNCmR1cmJpbldhdHNvblRlc3QobTRpbmYpIyBlbXBlb3JhIGJhc3RhbnRlDQoNCnJlc2V0dGVzdChtNCwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNGluZixdKSANCnJlc2V0dGVzdChtNGluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNGluZixdKSAjIG1lam9yYSBhbGdvDQoNCiMgRGVjaWRpbW9zIG5vIGNhbWJpYXJsbyBwb3JxdWUgZW1wZW9yYSBlbiBjYXNpIHRvZG8sIHkgZGUgcG9yIHNpIHRlbmlhIGJ1ZW5vcyBwLXZhbHVlcw0KDQoNCiMgbTUNCm91dGxpZXJUZXN0KG01KQ0KaW5mbHVlbmNlUGxvdChtNSkgIyAxLDgsMTIsMTUsMTgsMjQNCnBvczUgPC0gYyhUUlVFLHJlcChGQUxTRSw2KSxUUlVFLHJlcChGQUxTRSwzKSxUUlVFLHJlcChGQUxTRSwyKSxUUlVFLHJlcChGQUxTRSwyKSxUUlVFLHJlcChGQUxTRSw1KSxUUlVFLHJlcChGQUxTRSw2KSkNCg0KdHJhaW4uNWluZiA8LSB0cmFpbi41JiFwb3M1DQptNWluZiA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uNWluZixdKQ0KDQpuY3ZUZXN0KG01KQ0KbmN2VGVzdChtNWluZikgIyBlbXBlb3JhIGJhc3RhbnRlDQoNCnNoYXBpcm8udGVzdChyZXNpZChtNSkpDQpzaGFwaXJvLnRlc3QocmVzaWQobTVpbmYpKSAjIG1lam9yYSANCg0KZHVyYmluV2F0c29uVGVzdChtNSkNCmR1cmJpbldhdHNvblRlc3QobTVpbmYpICMgbm8gc2UgdmVyaWZpY2EgbGEgaGlwb3Rlc2lzIG51bGEgZGUgbm8gYXV0b2NvcnJlbGFjaW9uDQoNCnJlc2V0dGVzdChtNSwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNWluZixdKSANCnJlc2V0dGVzdChtNWluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNWluZixdKSAjIGVtcGVvcmENCg0KIyBEZWNpZGltb3Mgbm8gY2FtYmlhcmxvIHBvciBwZXJkZXJzZSBsYSBjb3JyZWxhY2nDs24NCg0KIyBOb3Rlc2UgcXVlIGVuIGxvcyBvcmlnaW5hbGVzIHNpZW1wcmUgc2UgY3VtcGxpYW4gbGFzIGhpcG90ZXNpcywgYXVucXVlIG5vIGVyYSBuZWNlc2FyaW8gcGFyYSBlbCBwcm9jZXNvDQoNCg0KDQoNCmxpc3RhX3Rlc3QgPC0gbGlzdCh0ZXN0LjEsdGVzdC4yLHRlc3QuMyx0ZXN0LjQsdGVzdC41KQ0KbGlzdGFfdHJhaW5oIDwtIGxpc3QodHJhaW4uMWgsdHJhaW4uMmgsdHJhaW4uM2gsdHJhaW4uNGgsdHJhaW4uNWgpDQpsaXN0YV90cmFpbiA8LSBsaXN0KHRyYWluLjEsdHJhaW4uMix0cmFpbi4zLHRyYWluLjQsdHJhaW4uNSkNCg0KDQptb2RlbG9zX2hpcCA8LSBjKCJTMSB0YXN0ZSB+IEgycyArIExhY3RpYyIsDQogICAgICAgICAgICAgICAgICJTMSB0YXN0ZSB+IExhY3RpYyIsDQogICAgICAgICAgICAgICAgICJTMiB0YXN0ZSB+IEgycyArIExhY3RpYyIsDQogICAgICAgICAgICAgICAgICJTMiB0YXN0ZSB+IExhY3RpYyIsDQogICAgICAgICAgICAgICAgICJTMyB0YXN0ZSB+IEgycyArIExhY3RpYyIsDQogICAgICAgICAgICAgICAgICJTMyB0YXN0ZSB+IExhY3RpYyIsDQogICAgICAgICAgICAgICAgICJTNCB0YXN0ZSB+IEgycyArIExhY3RpYyIsDQogICAgICAgICAgICAgICAgICJTNCB0YXN0ZSB+IExhY3RpYyIsDQogICAgICAgICAgICAgICAgICJTNSB0YXN0ZSB+IEgycyArIExhY3RpYyIsDQogICAgICAgICAgICAgICAgICJTNSB0YXN0ZSB+IExhY3RpYyIsDQogICAgICAgICAgICAgICAgICJOaXZlbCBkZSBzaWduaWZpY2FjaW9uIikNCg0KaGlwX1JMIDwtIGMoIkRpc3RyaWJ1Y2nDs25fbm9ybWFsIiwNCiAgICAgICAgICAgICJNZWRpYV8wIiwNCiAgICAgICAgICAgICJWYXJpYW56YV9ub19jb25zdGFudGUiLA0KICAgICAgICAgICAgIk5vX0F1dG9jb3JyZWxhY2nDs24iKQ0KcGxhY2Vob2xkZXIgPC0gdmVjdG9yKG1vZGUgPSAibG9naWNhbCIsbGVuZ3RoID0gMTEpDQpkZl9oaXBSTCA8LSBkYXRhLmZyYW1lKCIwIiA9IHBsYWNlaG9sZGVyLA0KICAgICAgICAgICAgICAgICAgICAgICAiMSIgPSBwbGFjZWhvbGRlciwNCiAgICAgICAgICAgICAgICAgICAgICAgIjIiID0gcGxhY2Vob2xkZXIsDQogICAgICAgICAgICAgICAgICAgICAgICIzIiA9IHBsYWNlaG9sZGVyLA0KICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPSBtb2RlbG9zX2hpcCkNCg0KY29sbmFtZXMoZGZfaGlwUkwpIDwtIGhpcF9STA0KDQpyIDwtIDENCmZvciAoZHRyYWluIGluIGxpc3RhX3RyYWluaCl7DQogIG1vZGVsLkhMLmxtIDwtIGxtKHRhc3RlIH4gSDJTICsgTGFjdGljLA0KICAgICAgICAgICAgICAgICAgICBkYXRhID0gY2hlZGRhcltkdHJhaW4sXSkNCiAgcmVzaWR1b3MgPC0gcmVzaWQobW9kZWwuSEwubG0pDQogIG5ld19yb3cgPC0gYygpDQogIA0KICBzaGFwIDwtIHJvdW5kKHNoYXBpcm8udGVzdChyZXNpZHVvcykkcC52YWx1ZSw0KQ0KICB0IDwtIHQudGVzdChyZXNpZHVvcywgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlDQogIHYgPC0gcm91bmQobmN2VGVzdChtb2RlbC5ITC5sbSkkcCw0KQ0KICBkdyA8LSByb3VuZChkdXJiaW5XYXRzb25UZXN0KG1vZGVsLkhMLmxtKSRwLDQpDQogIA0KICBuZXdfcm93ID0gYyhzaGFwLHQsdixkdykNCiAgZGZfaGlwUkxbcixdIDwtIG5ld19yb3cNCiAgciA9IHIgKyAyDQp9DQoNCg0KciA8LSAyDQpmb3IgKGR0cmFpbiBpbiBsaXN0YV90cmFpbil7DQogIG1vZGVsLkwubG0gPC0gbG0odGFzdGUgfkxhY3RpYywNCiAgICAgICAgICAgICAgICAgICBkYXRhID0gY2hlZGRhcltkdHJhaW4sXSkNCiAgcmVzaWR1b3MgPC0gcmVzaWQobW9kZWwuTC5sbSkNCiAgbmV3X3JvdyA8LSBjKCkNCiAgDQogIHNoYXAgPC0gcm91bmQoc2hhcGlyby50ZXN0KHJlc2lkdW9zKSRwLnZhbHVlLDQpDQogIHQgPC0gdC50ZXN0KHJlc2lkdW9zLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpJHAudmFsdWUNCiAgdiA8LSByb3VuZChuY3ZUZXN0KG1vZGVsLkwubG0pJHAsNCkNCiAgZHcgPC0gcm91bmQoZHVyYmluV2F0c29uVGVzdChtb2RlbC5MLmxtKSRwLDQpDQogIA0KICBuZXdfcm93ID0gYyhzaGFwLHQsdixkdykNCiAgZGZfaGlwUkxbcixdIDwtIG5ld19yb3cNCiAgciA9IHIgKyAyDQp9DQpkZl9oaXBSTFsxMSxdIDwtIGMocmVwKDAuMDUsNCkpDQpkZl9oaXBSTCAjIFRvZG9zIGxvcyBtb2RlbG9zIGN1bXBsZW4gbGFzIGhpcMOzdGVzaXMNCg0KDQoNCmVycjEgPC0gMA0KZm9yIChpIGluIDUpew0KICBkdHJhaW4gPC0gbGlzdGFfdHJhaW5oW1tpXV0NCiAgZHRlc3QgPC0gbGlzdGFfdGVzdFtbaV1dDQogIGRtb2QgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW2R0cmFpbixdKQ0KICBZIDwtIGNoZWRkYXJbZHRlc3QsXSR0YXN0ZQ0KICBZaGF0IDwtIHByZWRpY3Qob2JqID0gZG1vZCwgbmV3ZGF0YSA9IGNoZWRkYXJbZHRlc3QsXSkNCiAgZXJyMSA8LSBlcnIxICsgbWVhbigoWSAtIFloYXQpXjIpDQp9DQplcnIxIDwtIGVycjEvNQ0KZXJyMSAjIEgyUyArIExBQ1RJQyB0aWVuZSBlcnJvciBtZWRpbyAxMS42Mw0KDQoNCmVycjI8LTANCmZvciAoaSBpbiA1KXsNCiAgZHRyYWluIDwtIGxpc3RhX3RyYWluW1tpXV0NCiAgZHRlc3QgPC0gbGlzdGFfdGVzdFtbaV1dDQogIGRtb2QgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW2R0cmFpbixdKQ0KICBZIDwtIGNoZWRkYXJbZHRlc3QsXSR0YXN0ZQ0KICBZaGF0IDwtIHByZWRpY3Qob2JqID0gZG1vZCwgbmV3ZGF0YSA9IGNoZWRkYXJbZHRlc3QsXSkNCiAgZXJyMiA8LSBlcnIyICsgbWVhbigoWSAtIFloYXQpXjIpDQp9DQoNCg0KYGBgDQpgYGB7ciByZW5kZXI9bGVtb25fcHJpbnQsIGVjaG89RkFMU0V9DQpkZl9oaXBSTA0KDQoNCmBgYA0KQ2FsY3VsYW1vcyBsb3MgZXJyb3JlcyBkZSBjYWRhIG3DqXRvZG8gY29tbyBsYSBtZWRpYSBkZSBsb3MgZXJyb3JlcyBkZWwgbcOpdG9kbyBhcGxpY2FkbyBlbiBjYWRhIHNlZWQuIERlIGVzdGEgbWFuZXJhLCBlbCBlcnJvciBtZWRpbyBvYnRlbmlkbyBlczoNCg0KDQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnQgfQ0KZHQ8LWRhdGEuZnJhbWUoIjEiPTAsIjIiPTAscm93Lm5hbWVzPWMoImVycm9yZXMiKSkNCmNvbG5hbWVzKGR0KTwtIGMoIk1vZGVsbyBIMlMrTGFjdGljIiwiTGFjdGljIikNCmR0WzEsXTwtYyhlcnIxLGVycjIpDQpkdA0KYGBgDQoNCkNvbW8gZWwgZXJyb3IgZGVsIG1vZGVsbyBIMlMgKyBMYWN0aWMgZXMgbWVub3IsIGVzZSBlcyBlbCBtb2RlbG8gcXVlIGxsYW1hcmVtb3MgZmluYWwgeSBxdWUgc2UgYWp1c3RhcsOhIGxvIG1lam9yIHBvc2libGUgYSBsb3MgZGF0b3MgZGUgbnVlc3RybyBmaWNoZXJvLg0KDQojIENvbmNsdXNpw7NuOiBwcmVzZW50YWNpw7NuIGRlbCBtb2RlbG8gZmluYWwNCg0KRmluYWxtZW50ZSBwb3IgY29tcGFyYWNpw7NuIGRlIGxvcyBlcnJvcmVzIHNhYmVtb3MgcXVlIGVsIG1vZGVsbyBmaW5hbCBxdWUgcHJlc2VudGFtb3MgZXM6IHRhc3RlIH4gSDJTICsgTGFjdGljICwgcXVlIHRpZW5lIHNlbnRpZG8geWEgcXVlIEFjZXRpYyBubyBlcmEgc2lnbmlmaWNhdGl2YS4gb3RybyBoZWNobyBxdWUgbG8gcmVhZmlybWEgZXMgcXVlIGVuIGxhIGNvbnN0cnVjY2nDs24gZGUgbW9kZWxvcyBzYWxpZXJvbiBlbiB0b2RvcyBsb3MgY2Fzb3MgZXN0ZSBtb2RlbG8sIHNhbHZvIGVuIGVsIG3DqXRvZG8gYmFja3dhcmQgeSBlbiBlbCBtw6l0b2RvIGZvcndhcmQgZGUgbGEgcHJpbWVyYSBzZW1pbGxhLg0KDQo8IS0tIGFxdWkgaGFjZXJsbyB0YWJsYSBjb24gbG8gcXVlIG1lIGludGVyZXNhIC0tPg0KYGBge3IgaW5jbHVkZT1GQUxTRX0NCm1vZGVsLnkgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsZGF0YT1jaGVkZGFyKSANCmRmX3Jlc3VtZW4gPC0gdGlkeShtb2RlbC55KQ0KDQoNCmBgYA0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KZGZfcmVzdW1lbg0KYGBgDQoNClByZXNlbnRhbW9zIGVsIHN1bW1hcnkgZGUgbnVlc3RybyBtb2RlbG8sIGRlbCBxdWUgc2FjYXJlbW9zIG3DoXMgaW5mb3JtY2nDs24gZW4gdW4gZnV0dXJvLg0KDQpBIHN1IHZleiBlbnNlw7FhbW9zIGxvcyBncmFmaWNvcyBkZSBlc3RlIG1vZGVsbzoNCmBgYHtyIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTYuNSxmaWcuYWxpZ24gPSAnY2VudGVyJ30NCnBhcihtZnJvdz1jKDIsMikpDQpwbG90KG1vZGVsLnkpDQpgYGANCg0KQWhvcmEgdmFtb3MgYSBhc2VndXJhcm5vcyBxdWUgdmVyaWZpY2EgbGFzIGhpcMOzdGVzaXMgcGFyYSB1bmEgcmVncmVzacOzbiBsaW5lYWwgeSBhZGVtw6FzIGRlIHJldmlzYXIgY29uIG91dGxpZXJUZXN0ICBxdWUgbm8gdGVuZW1vcyBvdXRsaWVycy4NClRhbWJpw6luIHBsYW50ZWFtb3MgdW5hIGhpcMOzdGVzaXMgc29icmUgbGEgbnVsaWRhZCBkZSBsYSBtZWRpYSBkZSBsb3MgZXJyb3JlcyB5IHZlbW9zIHF1ZSBzdSB2YXJpYW56YSBlcyBjb25zdGFudGUgYWRlbcOhcyBkZSBjYWxjdWxhcmxhLg0KPCEtLSBBcXVpIGRlYmVyw61hIGlyIHRhYmxhIGNvbiBwdmFsdWVzIGRlIG5vcm1hbGlkYWQuLi4uIC0tPg0KYGBge3IgZWNobz1GQUxTRSwgcmVuZGVyPWxlbW9uX3ByaW50fQ0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsMSksIjIiID0gcmVwKDAsMSksIjMiID0gcmVwKDAsMSksIjQiID0gcmVwKDAsMSksIjUiID0gcmVwKDAsMSksIjYiID0gcmVwKDAsMSksIjciID0gcmVwKDAsMSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXM9YygibW9kZWwueSIpKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSAgICBjKCJwLU91dGxpZXJzIiwicC1Ob3JtYWxpZGFkIiwicC1NZWRpYSBudWxhIiwicC1Ib21vY2VkYXN0aWNpZGFkIiwiVmFsb3IgZGUgdmFyaWFuemEiLCJwLUF1dG9jb3JyZWxhY2nDs24iLCJwLUxpbmVhbGlkYWQiKQ0KZGZfcHZhbF9kcm9wX3AxWywxXSA8LSBvdXRsaWVyVGVzdChtb2RlbC55KSRwDQpkZl9wdmFsX2Ryb3BfcDFbLDJdIDwtIHNoYXBpcm8udGVzdChyZXNpZChtb2RlbC55KSkkcA0KZGZfcHZhbF9kcm9wX3AxWywzXSA8LSB0LnRlc3QocmVzaWQobW9kZWwueSksbXU9MCxhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlDQpkZl9wdmFsX2Ryb3BfcDFbLDRdIDwtIG5jdlRlc3QobW9kZWwueSkkcA0KZGZfcHZhbF9kcm9wX3AxWyw1XSA8LSBzcXJ0KGRldmlhbmNlKG1vZGVsLnkpL2RmLnJlc2lkdWFsKG1vZGVsLnkpKQ0KZGZfcHZhbF9kcm9wX3AxWyw2XSA8LSBkdXJiaW5XYXRzb25UZXN0KG1vZGVsLnkpJHANCmRmX3B2YWxfZHJvcF9wMVssN10gPC0gcmVzZXR0ZXN0KG1vZGVsLnksIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyKSRwLnZhbHVlDQpkZl9wdmFsX2Ryb3BfcDENCmBgYA0KDQpEaWNobyBlc3RvIHByb2NlZGVtb3MgYSBsYSBwcmVzZW50YWNpw7NuIGRlbCBtb2RlbG8gY29uIHN1cyBiZXRhcyBhc29jaWFkb3MsIHF1ZSBzaSBiaWVuIHNlIHB1ZWRlbiByZWNvZ2VyIGRlbCBzdW1tYXJ5LCB0YW1iacOpbiBsb3MgY2FsY3VsYW1vcyBkZSBmb3JtYSBtYXRyaWNpYWwgaWd1YWwgcXVlIHNlIGhpem8gY29uIGVsIG1vZGVsbyBjb21wbGV0byBlbiBzdSBtb21lbnRvLg0KDQpFbCByZXN1bHRhZG8gc2Vyw61hICoqdGFzdGUgfiAtMjcuNTkxODE1ICszLjk5NDYyNjcgSDJTICsxOS44ODcyMDQgTGFjdGljKioNCk7Ds3Rlc2UgcXVlIHNpZ3VlIHNpZW5kbyBhY29yZGUgYWwgbW9kZWxvIGNvbXBsZXRvIGRvbmRlIGVsICRcYmV0YSQgZGUgTGFjdGljIGVzIG11eSBzdXBlcmlvciBlbiBjb21wYXJhY2nDs24gYWwgZGUgSDJTLg0KDQpQcmVzZW50YW1vcyBhaG9yYSAkUl57Mn0kIHkgJFJeezJ9X3thZGp9JCwgZXN0YXMgY29tbyBhbnRlcyBzZSBwdWVkZW4gcmVjb2dlciBkaXJlY3RhbWVudGUgZGVsIHN1bW1hcnksIHRhbWJpw6luIGxhcyBjYWxjdWxhbW9zIGEgcGFydGlyIGRlIGxvcyBlcnJvcmVzIHkgbGEgdGFibGEgYW5vdmEsIGRhbmRvIGVsIHJlc3VsdGFkbyBkZSAwLjY1MTcwMjQgeSAwLjYyNTkwMjUgcmVzcGVjdGl2YW1lbnRlLiBBZGVtw6FzIHByZXNlbnRhbW9zIGVsIHZlY3RvciBkZSBwLXZhbG9yZXMuDQoNCjwhLS0gQXF1aSBpcmlhIHVuIHRhYmxhIHF1ZSBwcmVzZW50ZSB0b2RvIGVsbG8gLS0+DQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQojc3VtbWFyeShtb2RlbC55KSRjb2VmZlssNF0NCg0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsMSksIjIiID0gcmVwKDAsMSksIjMiID0gcmVwKDAsMSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXM9YygiUC12YWxvcmVzIikpDQoNCmNvbG5hbWVzKGRmX3B2YWxfZHJvcF9wMSkgPC0gICAgYygiSW50ZXJjZXB0IiwiSDJTIiwiTGFjdGljIikNCmRmX3B2YWxfZHJvcF9wMVsxLF0gPC0gYyhzdW1tYXJ5KG1vZGVsLnkpJGNvZWZmW1sxLDRdXSxzdW1tYXJ5KG1vZGVsLnkpJGNvZWZmW1syLDRdXSxzdW1tYXJ5KG1vZGVsLnkpJGNvZWZmW1szLDRdXSkNCg0KZGZfcHZhbF9kcm9wX3AxDQpgYGANCk9ic2VydmFtb3MgcXVlIHRvZG9zIGxvcyBwLXZhbG9yZXMgZXN0w6FuIHBvciBkZWJham8gZGUgbnVlc3RyYSBhbHBoYSBkZSByZWZlcmVuY2lhLg0KDQpUYW1iacOpbiBwcmVzZW50YW1vcyBpbnRlcnZhbG9zIHBhcmEgbGFzIGJldGFzIGRlIEJvbmZlcnJvbmkgeSBTY2hlZmbDqToNCjwhLS0gQXF1aSB2YSBlc28gLS0+DQpgYGB7ciBlY2hvPUZBTFNFLCByZW5kZXI9bGVtb25fcHJpbnR9DQphbHBoYSA8LSAwLjEwDQpiIDwtIHN1bW1hcnkobW9kZWwueSkkY29lZlsyOjMsIDFdDQpzLmIgPC0gc3VtbWFyeShtb2RlbC55KSRjb2VmWzI6MywgMl0NCmcgPC0gMw0KbiA8LSBucm93KGNoZWRkYXIpDQpwIDwtIG5jb2woc3VtbWFyeShtb2RlbC55KSRjb2VmKQ0KdF90ZW8gPC0gcXQoMSAtIGFscGhhIC8gKDIgKiBnKSwgbiAtIHApDQpCb21TaW1DSSA8LSBtYXRyaXgoYyhiIC0gdF90ZW8gKiBzLmIsIGIgKyB0X3RlbyAqIHMuYiksIG5jb2wgPSAyKQ0KY29uZiA8LSBjKCI1JSIsICI5NSUiKQ0KYm5hbSA8LSBjKCJIMlMiLCAiTGFjdGljIikNCmRpbW5hbWVzKEJvbVNpbUNJKSA8LSBsaXN0KGJuYW0sIGNvbmYpDQojIEJvbVNpbUNJDQpjMTwtQm9tU2ltQ0lbMSxdDQpjMjwtQm9tU2ltQ0lbMixdDQpRIDwtIHAgLSAxDQpmX3RlbyA8LSBxZigwLjksIFEsIG4gLSBwKSMwLjkgbm8gc2VyaWEgMC45NT8NClNjaFNpbUNJIDwtIG1hdHJpeChjKGIgLSBzcXJ0KFEgKiBmX3RlbykgKiBzLmIsIGIgKyBzcXJ0KFEgKiBmX3RlbykgKiBzLmIpLCBuY29sID0gMikNCmNvbmYgPC0gYygiNSUiLCAiOTUlIikNCmJuYW0gPC0gYygiSDJTIiwgIkxhY3RpYyIpDQpkaW1uYW1lcyhTY2hTaW1DSSkgPC0gbGlzdChibmFtLCBjb25mKQ0KIyBTY2hTaW1DSQ0KZDE8LVNjaFNpbUNJWzEsXQ0KZDI8LVNjaFNpbUNJWzIsXQ0KZGZfcHZhbF9kcm9wX3AxIDwtIGRhdGEuZnJhbWUoIjEiID0gcmVwKDAsMyksIjIiID0gcmVwKDAsMyksIjMiID0gcmVwKDAsMyksIjQiID0gcmVwKDAsMyksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXM9YygiSDJTIiwiTGFjdGljIiwiUG9yY2VudGFqZSIpKQ0KY29sbmFtZXMoZGZfcHZhbF9kcm9wX3AxKSA8LSAgICBjKCJCb25mZXJyb25pIiwiQm9uZmVycm9uaSIsIlNjaGVmZsOpIiwiU2NoZWZmw6kiKQ0KZGZfcHZhbF9kcm9wX3AxWzEsXSA8LSBjKGMxLGQxKQ0KZGZfcHZhbF9kcm9wX3AxWzIsXSA8LSBjKGMyLGQyKQ0KZGZfcHZhbF9kcm9wX3AxWzMsXSA8LSBjKCI1JSIsIjk1JSIsIjUlIiwiOTUlIikNCmRmX3B2YWxfZHJvcF9wMQ0KYGBgDQpGaW5hbG1lbnRlIGJ1c2NhbW9zIHVuYSByZXByZXNlbnRhY2nDs24gZGUgbGEgcmVncmVzacOzbiBxdWUgdGVuZW1vcyBlbiAzIGRpbWVuc2lvbmVzIHlhIHF1ZSBlbCBtb2RlbG8gZmluYWwgY29uc3RhIGRlIHVuYSB2YXJpYWJsZSByZXNwdWVzdGEgeSBkb3MgcHJlZGljdG9yYXMgeSB2ZW1vcyBlbCBwbGFubyBkZSByZWdyZXNpw7NuLCBtYXJjYW5kbyBlbiByb2pvIGxhcyBvYnNlcnZhY2lvbmVzIHF1ZSBwZW9yIHNlIGFqdXN0YW4uDQo8IS0tIEFxdWkgdmEgZXNvLCBzaSBsbyBwdWVkZSBvbmVyIG90cm8gbWVqb3IsIHBxIGEgbWkgaGF5IHVuYSBncmFmaWNhIHF1ZSBubyBzZSBtZSBlamVjdXRhIC0tPg0KDQpgYGB7ciBlY2hvPUZBTFNFfQ0KcGxvdF9seSh4PUgyUywgeT1MYWN0aWMsIHo9dGFzdGUsIHR5cGU9InNjYXR0ZXIzZCIsIG1vZGU9Im1hcmtlciIsIGNvbG9yPXRhc3RlKSAlPiUgDQogIGxheW91dChzY2VuZSA9IGxpc3QoeGF4aXMgPSBsaXN0KHRpdGxlID0gJ0gyUyAoJSknKSwNCiAgICAgICAgICAgICAgICAgICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAnTGFjdGljICglKScpLA0KICAgICAgICAgICAgICAgICAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICdUYXN0ZSAoMC0xMDApJykpKQ0KcGxhbmVyZWcgPC0gc2NhdHRlcnBsb3QzZCh4PUgyUywgeT1MYWN0aWMsIHo9dGFzdGUsIHBjaD0xNiwgY2V4LmxhYj0xLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBoaWdobGlnaHQuM2Q9VFJVRSwgdHlwZT0iaCIsIHhsYWI9J0gyUyAoJSknLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB5bGFiPSdMYWN0aWMgKCUpJywgemxhYj0nVGFzdGUgKDAtMTAwKScpDQpwbGFuZXJlZyRwbGFuZTNkKG1vZGVsLnksIGx0eS5ib3g9InNvbGlkIiwgY29sPSdtZWRpdW1ibHVlJykNCmBgYA0KDQoNCg0KIyAgQW5leG8NCg0KYGBge3IgZWNobyBUUlVFLGV2YWw9RkFMU0V9DQoNCg0KaW5zdGFsbC5wYWNrYWdlcygiZmFyYXdheSIpDQppbnN0YWxsLnBhY2thZ2VzKCJsZWFwcyIpDQppbnN0YWxsLnBhY2thZ2VzKCJNQVNTIikNCmluc3RhbGwucGFja2FnZXMoIlBBU1dSIikNCmluc3RhbGwucGFja2FnZXMoImNhciIpDQppbnN0YWxsLnBhY2thZ2VzKCJnZ3Bsb3QyIikNCmluc3RhbGwucGFja2FnZXMoIkdHYWxseSIpDQppbnN0YWxsLnBhY2thZ2VzKCJjb3JycGxvdCIpDQppbnN0YWxsLnBhY2thZ2VzKCJzY2F0dGVycGxvdDNkIikNCmluc3RhbGwucGFja2FnZXMoImxtdGVzdCIpDQppbnN0YWxsLnBhY2thZ2VzKCJwbG90bHkiKQ0KaW5zdGFsbC5wYWNrYWdlcygibWl4bG0iKQ0KDQoNCmxpYnJhcnkoZmFyYXdheSkNCmxpYnJhcnkobGVhcHMpDQpsaWJyYXJ5KE1BU1MpDQpsaWJyYXJ5KFBBU1dSKQ0KbGlicmFyeShjYXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KEdHYWxseSkNCmxpYnJhcnkoY29ycnBsb3QpDQpsaWJyYXJ5KHBsb3RseSkNCmxpYnJhcnkoc2NhdHRlcnBsb3QzZCkNCmxpYnJhcnkobG10ZXN0KQ0KbGlicmFyeShtaXhsbSkNCg0KDQoNCg0KDQojIDEpIEludHJvZHVjY2lvbg0KDQpkYXRhKGNoZWRkYXIpDQphdHRhY2goY2hlZGRhcikNCg0KIyBWYXJpYWJsZSBSZXNwdWVzdGE6IHRhc3RlDQojIFZhcmlhYmxlcyBQcmVkaWN0b3JhczogQWNldGljLCBIMlMsIExhY3RpYw0KDQoNCiMgRXN0dWRpYW1vcyBlbCB0aXBvIGRlIGxhcyB2YXJpYWJsZXMgcXVlIHZhbiBhIGZvcm1hciBwYXJ0ZSBkZSBsb3MgcG9zaWJsZXMgbW9kZWxvcw0Kc2FwcGx5KGNoZWRkYXIsIGNsYXNzKSAjIHRvZGFzIGxhcyB2YXJpYWJsZXMgc29uIG51bWVyaWNhcw0KaGVhZChjaGVkZGFyKQ0KDQojIENvbXByb2JhbW9zIHF1ZSBubyBoYXkgZW50cmFkYXMgdmFjaWFzDQphbnkoaXMubmEoY2hlZGRhcikpDQoNCiMgRGUgaGFiZXJsYXMgaGFiaWRvLCBwb2RyaWFtb3MgaGFiZXIgdG9tYWRvIGxhcyBzaWd1aWVudGVzIGRlY2lzaW9uZXM6DQojICAtIGVsaW1pbmFyIGxhcyBvYnNlcnZhY2lvbmVzIGNvbiB2YWxvcmVzIE5BDQojICAtIGVsaW1pbmFyIHZhcmlhYmxlcyBzaSBtdWNoYXMgZGUgbGFzIGVudHJhZGFzIHZhY2lhcyBhcGFyZWNlbiBlbiBlbGxhDQojICAtIGVtcGxlYXIgbcOpdG9kb3MgcGFyYSBwcmVkZWNpciBxdWUgdmFsb3JlcyBkZWJlcmlhbiBhcGVyY2VyIGVuIGRpY2hhcyBlbnRyYWRhcw0KDQoNCg0KIyBIaXN0b2dyYW1hcyBkZSB0b2RhcyBsYXMgdmFyaWFibGVzDQppZHMgPC0gbmFtZXMoY2hlZGRhcikNCmxheW91dChtYXRyaXgoMTo0LCBucm93ID0gMSkpDQp5X2xhYl9zdHJpbmcgPC0gIkNhbnRpZGFkIg0KZm9yIChpZCBpbiBpZHMpIHsNCiAgaGlzdChjaGVkZGFyWywgaWRdLCB4bGFiID0gaWQsIHlsYWIgPSB5X2xhYl9zdHJpbmcsIG1haW4gPSBwYXN0ZSgiSGlzdG9ncmFtIG9mICIsIGlkKSkNCiAgeV9sYWJfc3RyaW5nIDwtICIiDQp9DQoNCg0KIyBHcmFmaWNhcyBkZSBsYXMgcmVsYWNpb25lcyBlbnRyZSB2YXJpYWJsZXMuDQpwbG90KGNoZWRkYXIpDQoNCiMgR3JhZmljYXMgZGUgZGlzcGVyc2lvbiBlbnRyZSBsYSB2YXJpYWJsZSByZXNwdWVzdGEgInRhc3RlIiB5IGxhcyB2YXJpYWJsZXMgcHJlZGljdG9yYXMuDQpsYXlvdXQobWF0cml4KDE6MywgbnJvdyA9IDEpKQ0KDQpwbG90KEFjZXRpYywgdGFzdGUsDQogICAgIG1haW4gPSAiUmVsYWNpw7NuIGVudHJlIFRhc3RlIHkgQWNldGljIiwNCiAgICAgeGxhYiA9ICJBY2V0aWMiLCB5bGFiID0gIlRhc3RlIiwNCiAgICAgcGNoID0gMTksIGZyYW1lID0gRkFMU0UpDQoNCg0KcGxvdChIMlMsIHRhc3RlLA0KICAgICBtYWluID0gIlJlbGFjacOzbiBlbnRyZSBUYXN0ZSB5IEgyUyIsDQogICAgIHhsYWIgPSAiSDJTIiwgeWxhYiA9ICJUYXN0ZSIsDQogICAgIHBjaCA9IDE5LCBmcmFtZSA9IEZBTFNFKQ0KDQoNCnBsb3QoTGFjdGljLCB0YXN0ZSwNCiAgICAgbWFpbiA9ICJSZWxhY2nDs24gZW50cmUgVGFzdGUgeSBMYWN0aWMiLA0KICAgICB4bGFiID0gIkxhY3RpYyIsIHlsYWIgPSAiVGFzdGUiLA0KICAgICBwY2ggPSAxOSwgZnJhbWUgPSBGQUxTRSkNCg0KDQpsYXlvdXQobWF0cml4KDE6MSwgbnJvdyA9IDEpKQ0Kc3VtbWFyeShjaGVkZGFyKQ0KDQoNCg0KDQoNCiMgMikgRXN0dWRpbyB5IGV2YWx1YWNpb24gZGVsIG1vZGVsbyBjb21wbGV0bw0KDQp4IDwtIG1vZGVsLm1hdHJpeCggfiBBY2V0aWMgKyBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyKQ0KYmV0YWhhdCA8LSBzb2x2ZShjcm9zc3Byb2QoeCwgeCksIGNyb3NzcHJvZCh4LCB0YXN0ZSkpDQpiZXRhaGF0IDwtIGMoYmV0YWhhdCkNCmJldGFoYXQNCg0KIyBDb21wcm9iYW1vcyBlbCByZXN1bHRhZG8gY29uIGZ1bmNpb25lcyB5YSBpbXBsZW1lbnRhZGFzDQptb2RlbC5hbGwgPC0gbG0odGFzdGUgfiAuLCBkYXRhID0gY2hlZGRhcikNCnN1bW1hcnkobW9kZWwuYWxsKQ0KbW9kZWwuYWxsJGNvZWZmaWNpZW50cw0KDQphbm92YShtb2RlbC5hbGwpDQoNCg0KDQojIEludGVydmFsb3MgZGUgY29uZmlhbnphIGRlIGxhcyBiZXRhcyBkZWwgbW9kZWxvIGNvbXBsZXRvDQpjb25maW50KG1vZGVsLmFsbCkNCg0KIyBPYnNlcnZhbW9zIHF1ZSAwIGVzdGEgZW4gZWwgaW50ZXJ2YWxvIGRlIGNvbmZpYW56YSBkZSBiZXRhXzAgeSBiZXRhX0FjZXRpYywgcGxhbnRlYW1vcyBkb3MgdGVzdHMNCiMgICAgY29uIGhpcMOzdGVzaXMgbnVsYSBiZXRhX2kgPSAwIHkgaGlwb3Rlc2lzIGFsdGVybmF0aXZhIGJldGFfaSAhPSAwLg0KDQojIENvbWVuemFtb3MgY29uIGJldGFfQWNldGljIHB1ZXMgZWwgdmFsb3IgZXN0aW1hZG8gZXMgbcOhcyBjZXJjYW5vIGEgMCBxdWUgZWwgZGUgYmV0YV8wDQptb2Rub0FjZXRpYyA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYywgZGF0YT1jaGVkZGFyKQ0KYW5vdmEobW9kbm9BY2V0aWMsbW9kZWwuYWxsKSAjIG5vIHNvbG8gZWwgcC12YWxvciA+IDAuMDUgc2lubyBxdWUgZGUgaGVjaG8gcC12YWxvciB+IDEsIGFjZXB0YW1vcyBsYSBoaXBvdGVzaXMgbnVsYS4NCg0KbW9kbm9JbnRlcmNlcHRvciA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYyArIDAsIGRhdGE9Y2hlZGRhcikgIyBtb2RlbG8gcmVkdWNpZG8gc2luIGludGVyY2VwdG9yDQphbm92YShtb2Rub0ludGVyY2VwdG9yLG1vZGVsLmFsbCkgIyBlbCBwLXZhbG9yIGVzIG1lbm9yIHF1ZSAwLjA1LCBsdWVnbyBubyBlcyBzdWZpY2llbnRlIHBhcmEgcmVjaGF6YXIgbGEgaGlwb3Rlc2lzIG51bGENCg0KDQojIFZlYW1vcyBsb3MgcC12YWxvcmVzIGRlIGxhcyB2YXJpYWJsZXMgcHJlZGljdG9yYXMNCnN1bW1hcnkobW9kZWwuYWxsKSRjb2VmZlssNF0NCiMgT2JzZXJ2YW1zbyBxdWUgZWwgcC12YWxvciBkZSBBY2V0aWMgZXMgZWwgbWFzIGVsZXZhZG8sIGVzdGUgcmVzdWx0YWRvIGp1bnRvIGNvbiBlbCBjb250cmF0ZSBkZSBoaXBvdGVzaXMgcXVlIGhlbW9zIGhlY2hvDQojICBwb2RlbW9zIGRlZHVjaXIgcXVlIGxhIHZhcmlhYmxlIEFjZXRpYyBubyBzZXJhIG11eSByZWxldmFudGUgcGFyYSBlbCBlc3R1ZGlvIGRlIGxvcyBkaXN0aW50b3MgbW9kZWxvcyBxdWUgZXN0dWRpYXJlbW9zLg0KDQoNCiMgQ29ycmVsYWNpb25lcyBkZSBsYXMgdmFyaWFibGVzIHF1ZSBpbnRlcnZpZW5lbiBlbiBlbCBtb2RlbG8gY29tcGxldG8NCmNvcihjaGVkZGFyKQ0KZ2dwYWlycyhjaGVkZGFyKQ0KDQptYXRfY29yIDwtIGNvcihjaGVkZGFyLCBtZXRob2QgPSAicGVhcnNvbiIpDQpjb3JycGxvdChtYXRfY29yLCB0eXBlID0gInVwcGVyIiwgb3JkZXIgPSAiaGNsdXN0IiwgdGwuY29sID0gImJsYWNrIiwgdGwuc3J0ID0gNDUpDQoNCg0KIyBQb3IgdWx0aW1vIHZlYW1vcyBzaSBoYXkgb3V0bGllcnMgZW4gZWwgbW9kZWxvIGNvbXBsZXRvDQpNb2RlbC5hbGw8LWZvcnRpZnkobW9kZWwuYWxsKQ0Kb3V0bGllclRlc3QobW9kZWwuYWxsKSAjIG5vIGxvcyBoYXkNCg0KIyBQb3IgZWwgbWV0b2RvIGRlIEJvbmZlcnJvbmkNCmFscGhhIDwtIDAuMDUNCkJDViA8LSBxdCgxLWFscGhhLygyKjMwKSwyNikgIyBlbCB2YWxvciBjcml0aWNvIGRlIEJvbmZlcnJvbmkgdF97MS1hbHBoYS8ybjtuLXAtMX0sIG49MzAscD0zDQpCQ1YNCnN1bShhYnMocnN0dWRlbnQobW9kZWwuYWxsKSk+QkNWKSAjIGVsIG1ldG9kbyBubyBub3MgZGEgbmluZ3VuYSBvYnNlcnZhY2lvbg0KDQpzb3J0KGFicyhyc3RhbmRhcmQobW9kZWwuYWxsKSksZGVjcmVhc2luZyA9IFRSVUUpWzE6M10gIyBlc3RvcyB2YWxvcmVzIGVzdGFuIHJlbGF0aXZhbWVudGUgbGVqYW5vcyBkZSBCQ1YNCg0KDQojIFZlYW1vcyBzaSBwb3IgaW5mbHVlbmNlSW5kZXhQbG90KCkgaGF5IGFsZ3VuYSBvYnNlcnZhY2lvbiBxdWUgcHVlZGEgc2VyIHJlbGV2YW50ZQ0KaW5mbHVlbmNlSW5kZXhQbG90KG1vZGVsLmFsbCkgIyBlbiBsYSB0ZXJjZXJhIGdyYWZpY2Egc2UgdmUgcXVlIGxhIG9ic2VydmFjaW9uIDE1IHRpZW5lIHVuIGNvbXBvcnRhbWllbnRvIGFub3JtYWwNCg0KIyBDb21wcm9iZW1vcyBzaSBsb3Mgc3VwdWVzdG9zIGRlIGxvcyBtb2RlbG9zIGRlIHJlZ3Jlc2lvbiBsaW5lYWwgbWVqb3JhbiBhbCByZXRpcmFyIGVzdGEgb2JzZXJ2YWNpb24NCiMgIGRlIG51ZXN0cm8gZGF0YXNldC4gRGUgc2VyIGFzaSwgYWNlcHRhbW9zIHF1ZSBwdWVkYSBzZXIgdW5hIG9ic2VydmFjaW9uIHF1ZSBwZWp1ZGlxdWUgYSBudWVzdHJvIG1vZGVsby4NCm1vZGVsLmFsbF8xNTwtIGxtKHRhc3RlIH4gLiwgZGF0YSA9IGNoZWRkYXJbLTE1LF0pDQoNCiMgSG9tb2NlZGFzdGljaWRhZA0KbmN2VGVzdChtb2RlbC5hbGwpDQpuY3ZUZXN0KG1vZGVsLmFsbF8xNSkgIyBlbXBlb3JhDQoNCiMgTm9ybWFsaWRhZA0Kc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLmFsbCkpDQpzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuYWxsXzE1KSkjIG1lam9yYQ0KDQojIEF1dG9jb3JyZWxhY2lvbg0KZHVyYmluV2F0c29uVGVzdChtb2RlbC5hbGwpDQpkdXJiaW5XYXRzb25UZXN0KG1vZGVsLmFsbF8xNSkjIG1lam9yYQ0KDQojIExpbmVhbGlkYWQNCnJlc2V0dGVzdChtb2RlbC5hbGwsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyKQ0KcmVzZXR0ZXN0KG1vZGVsLmFsbF8xNSwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXIpIyBlbXBlb3JhDQoNCiMgRW4gZWwgY29tcHV0byBnbG9iYWwgbm8gcGFyZWNlIHF1ZSBsb3MgcC12YWxvcmVzIGRlIGVzdG9zIHRlc3RzIGRlbiBhIGVudGVuZGVyIHVuYSBtZWpvcmlhIGdlbmVyYWwgZGVsIG1vZGVsby4NCiMgIFNpIGJpZW4gZXMgY2llcnRvLCB0YW1wb2NvIGxvcyBlbXBlb3JhIHkgZGVwZW5kaWVuZG8gZGVsIGNyaXRlcmlvIGEgc2VndWlyIHBvZHJpYW1vcyBkZWNpZGlyIHNpIGVzIHJlbGV2YW50ZSBvIG5vLg0KIyAgTm9zb3Ryb3MgaGVtb3MgZGVjaWRpZG8gbm8gY29uc2lkZXJhciBsYSBvYnNlcnZhY2lvbiAxNSBjb21vIHRhbC4NCg0KDQoNCg0KDQojIDMpIFNlbGVjY2lvbiBkZWwgbWVqb3IgbW9kZWxvLiBNZXRvZG9zIHBvciBwYXNvcyB5IHBvciBjcml0ZXJpb3MNCg0KIyBTZXBhcmFjaW9uIGRlbCBkYXRhc2V0IGVuIGNvbmp1bnRvcyBkZSBlbnRyZW5hbWllbnRvIHkgdGVzdCAoNzAtMzAlKQ0KDQojIEhlbW9zIGNvbnNpZGVyYWRvIHZhcmlhcyBzZW1pbGxhcyBwYXJhIGFiYXJjYXIgbcOhcyBtb2RlbG9zLiBBZGVtw6FzLCBoZW1vcyBpbnRlbnRhZG8gZXZpdGFyDQojICBlbiBsYSBtZWRpZGEgZGUgbG8gcG9pYmxlIHF1ZSBzZSByZXBpdGFuIG11Y2hvcyBlbGVtZW50b3MgZW4gbG9zIGRpc3RpbnRvcyBjb25qdW50b3MgZGUgdGVzdCBzZWxlY2Npb25hZG9zLg0KDQpzZXQuc2VlZCgxKQ0KdHJhaW4uMSA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC4xIDwtICghdHJhaW4uMSkNCnN1bSh0ZXN0LjEpDQptb2RlbC5hbGwxIDwtIGxtKHRhc3RlIH4gLiwgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMSxdKQ0KDQpzZXQuc2VlZCgxMTAwKQ0KdHJhaW4uMiA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC4yIDwtICghdHJhaW4uMikNCnN1bSh0ZXN0LjIpDQpzdW0odGVzdC4xPT1UUlVFICYgdGVzdC4yPT1UUlVFKSNzb2xvIDEgcHJlc2VndWltb3MNCm1vZGVsLmFsbDIgPC0gbG0odGFzdGUgfiAuLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yLF0pDQoNCnNldC5zZWVkKDUpDQp0cmFpbi4zIDwtIHNhbXBsZShjKFRSVUUsIEZBTFNFKSwgc2l6ZSA9IG5yb3coY2hlZGRhciksIHJlcGxhY2UgPSBUUlVFLCBwcm9iID0gYygwLjcsIDAuMykpDQp0ZXN0LjMgPC0gKCF0cmFpbi4zKQ0Kc3VtKHRlc3QuMykNCnN1bSh0ZXN0LjE9PVRSVUUgJiB0ZXN0LjM9PVRSVUUpDQpzdW0odGVzdC4yPT1UUlVFICYgdGVzdC4zPT1UUlVFKQ0KbW9kZWwuYWxsMyA8LSBsbSh0YXN0ZSB+IC4sIGRhdGEgPSBjaGVkZGFyW3RyYWluLjMsXSkNCg0KDQoNCiMgaSkgQkFDS1dBUkQgKGFscGhhPTAuMDUpDQoNCmRyb3AxKG1vZGVsLmFsbDEsIHRlc3QgPSAiRiIpDQojIHF1aXRhbW9zIEFjZXRpYyBkZWwgbW9kZWxvIHBvciBzZXIgbGEgZGUgbWF5b3IgcC12YWxvcg0KDQptb2RlbC51cGRhdGVCMSA8LSB1cGRhdGUobW9kZWwuYWxsMSwgLiB+IC4gLSBBY2V0aWMpDQpkcm9wMShtb2RlbC51cGRhdGVCMSwgdGVzdCA9ICJGIikNCiMgcXVpdGFtb3MgSDJTIGRlbCBtb2RlbG8gcG9yIHNlciBsYSBkZSBtYXlvciBwLXZhbG9yDQoNCm1vZGVsLnVwZGF0ZUIyIDwtIHVwZGF0ZShtb2RlbC51cGRhdGVCMSwgLiB+IC4gLSBIMlMpDQpkcm9wMShtb2RlbC51cGRhdGVCMiwgdGVzdCA9ICJGIikNCiMgdGVybWluYSBlbCBwcm9jZXNvIHB1ZXMgZWwgcC12YWxvciBkZSBMYWN0aWMgbm8gbGxlZ2EgYSBhbHBoYQ0KDQptb2RlbC4xIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xLF0pDQpzdW1tYXJ5KG1vZGVsLjEpDQoNCiMgUGFyYSBldml0YXIgcmVwZXRpciBlc3RlIHByb2Nlc28gdXNhbW9zIGVsIHBhY2thZ2UgbWl4bG0gY29uIGVsIHF1ZSBvYnRlbmVtb3MgbG9zIG1pc21vcyByZXN1bHRhZG9zLg0KbW9kZWwuMSA8LSBtaXhsbTo6YmFja3dhcmQobW9kZWwuYWxsMSwgYWxwaGE9MC4wNSkNCnN1bW1hcnkobW9kZWwuMSkgIyBMQUNUSUMNCg0KbW9kZWwuMiA8LSBtaXhsbTo6YmFja3dhcmQobW9kZWwuYWxsMiwgYWxwaGE9MC4wNSkNCnN1bW1hcnkobW9kZWwuMikgIyBIMlMgKyBMQUNUSUMNCg0KbW9kZWwuMyA8LSBtaXhsbTo6YmFja3dhcmQobW9kZWwuYWxsMywgYWxwaGE9MC4wNSkNCnN1bW1hcnkobW9kZWwuMykgIyBIMlMgKyBMQUNUSUMNCg0KDQoNCiMgaWkpIEZPUldBUkQgKGFscGhhPTAuMDUpDQpTQ09QRSA8LSAofiAuICsgQWNldGljICsgSDJTICsgTGFjdGljKQ0KbW9kZWwuaW5pY2lhbCA8LSBsbSh0YXN0ZSB+IDEsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSkgIyBzb2xvIGNvbiB0ZXJtaW5vIGluZGVwZW5kaWVudGUNCg0KYWRkMShtb2RlbC5pbmljaWFsLCBzY29wZSA9IFNDT1BFLCB0ZXN0ID0gIkYiKQ0KIyBBw7FhZGltb3MgTGFjdGljIHBvciBzZXIgbGEgdmFyaWFibGUgcHJlZGljdG9yYSBjb24gbWVub3IgcC12YWxvcg0KbW9kZWwudXBkYXRlRjEgPC0gdXBkYXRlKG1vZGVsLmluaWNpYWwsIC4gfiAuICsgTGFjdGljKQ0KDQphZGQxKG1vZGVsLnVwZGF0ZUYxLCBzY29wZSA9IFNDT1BFLCB0ZXN0ID0gIkYiKQ0KIyBObyBhw7FhZGltb3MgbmluZ3VuYSB2YXJpYWJsZSBwdWVzIHRvZG9zIGxvcyBwLXZhbG9yZXMgc3VwZXJhbiBsYSBiYXJyZXJhIGRlIGFscGhhDQoNCm1vZGVsLjFhIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xLF0pDQpzdW1tYXJ5KG1vZGVsLjFhKQ0KDQoNCiMgQWwgaWd1YWwgcXVlIGVuIEJBQ0tXQVJEIHVzYW1vcyBlbCBwYXF1ZXRlIG1peGxtIHBhcmEgYXV0b21hdGl6YXIgZWwgcHJvY2VzbyBkZSBGT1JXQVJELg0KbW9kZWwuMWEgPC0gbWl4bG06OmZvcndhcmQobW9kZWwuYWxsMSwgYWxwaGE9MC4wNSkNCnN1bW1hcnkobW9kZWwuMWEpICMgTEFDVElDDQoNCm1vZGVsLjJhIDwtIG1peGxtOjpmb3J3YXJkKG1vZGVsLmFsbDIsIGFscGhhPTAuMDUpDQpzdW1tYXJ5KG1vZGVsLjJhKSAjIEgyUyArIExBQ1RJQw0KDQptb2RlbC4zYSA8LSBtaXhsbTo6Zm9yd2FyZChtb2RlbC5hbGwzLCBhbHBoYT0wLjA1KQ0Kc3VtbWFyeShtb2RlbC4zYSkgIyBIMlMgKyBMQUNUSUMNCg0KIyBOw7N0ZXNlIHF1ZSBsb3MgbW9kZWxvcyBvYnRlbmlkb3MgcG9yIEJBQ0tXQVJEIHkgRk9SV0FSRCBjb2luY2lkZW4gcGFyYSBjYWRhIGNvbmp1bnRvIHRyYWluLg0KDQoNCg0KIyBpaWkpIENSSVRFUklPUw0KDQojIFIyIGFqdXN0YWRvDQptb2RlbHMxIDwtIHJlZ3N1YnNldHModGFzdGUgfiAuLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xLF0pDQptb2RlbHMyIDwtIHJlZ3N1YnNldHModGFzdGUgfiAuLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yLF0pDQptb2RlbHMzIDwtIHJlZ3N1YnNldHModGFzdGUgfiAuLCBkYXRhID0gY2hlZGRhclt0cmFpbi4zLF0pDQoNCnN1bW1hcnkobW9kZWxzMSkNCnN1bW1hcnkobW9kZWxzMikNCnN1bW1hcnkobW9kZWxzMykNCg0KTVIyYWRqMSA8LSBzdW1tYXJ5KG1vZGVsczEpJGFkanIyDQpNUjJhZGoyIDwtIHN1bW1hcnkobW9kZWxzMikkYWRqcjINCk1SMmFkajMgPC0gc3VtbWFyeShtb2RlbHMzKSRhZGpyMg0KDQpzdW1tYXJ5KG1vZGVsczEpJHdoaWNoW3doaWNoLm1heChNUjJhZGoxKSwgXQ0Kc3VtbWFyeShtb2RlbHMyKSR3aGljaFt3aGljaC5tYXgoTVIyYWRqMiksIF0NCnN1bW1hcnkobW9kZWxzMykkd2hpY2hbd2hpY2gubWF4KE1SMmFkajMpLCBdDQoNCg0KDQojIENwIGRlIE1hbGxvd3MNCk1DcDEgPC0gc3VtbWFyeShtb2RlbHMxKSRjcA0KTUNwMiA8LSBzdW1tYXJ5KG1vZGVsczIpJGNwDQpNQ3AzIDwtIHN1bW1hcnkobW9kZWxzMykkY3ANCg0KDQpzdW1tYXJ5KG1vZGVsczEpJHdoaWNoW3doaWNoLm1pbihNQ3AxKSwgXQ0Kc3VtbWFyeShtb2RlbHMyKSR3aGljaFt3aGljaC5taW4oTUNwMiksIF0NCnN1bW1hcnkobW9kZWxzMykkd2hpY2hbd2hpY2gubWluKE1DcDMpLCBdDQoNCg0KIyBDcml0ZXJpbyBkZSBJbmZvcm1hY2lvbiBkZSBCYXllcyAoQklDKQ0KTUJJQzEgPC0gc3VtbWFyeShtb2RlbHMxKSRiaWMNCk1CSUMyIDwtIHN1bW1hcnkobW9kZWxzMikkYmljDQpNQklDMyA8LSBzdW1tYXJ5KG1vZGVsczMpJGJpYw0KDQpzdW1tYXJ5KG1vZGVsczEpJHdoaWNoW3doaWNoLm1pbihNQklDMSksIF0NCnN1bW1hcnkobW9kZWxzMikkd2hpY2hbd2hpY2gubWluKE1CSUMyKSwgXQ0Kc3VtbWFyeShtb2RlbHMzKSR3aGljaFt3aGljaC5taW4oTUJJQzMpLCBdDQoNCiMgQ3JpdGVyaW8gZGUgSW5mb3JtYWNpb24gZGUgQWthaWtlIChBSUMpDQpzdGVwQUlDKG1vZGVsLmFsbDEsIHNjb3BlID0gU0NPUEUsIGsgPSAyKQ0Kc3RlcEFJQyhtb2RlbC5hbGwyLCBzY29wZSA9IFNDT1BFLCBrID0gMikNCnN0ZXBBSUMobW9kZWwuYWxsMywgc2NvcGUgPSBTQ09QRSwgayA9IDIpDQoNCg0KIyBQYXJhIGVsIGNvbmp1bnRvIHRyYWluLjEgYXBhcmVjZW4gbW9kZWxvcyBjb24gTGFjdGljIHkgSDJTICsgTGFjdGljIGNvbW8gdmFyaWFibGVzIHByZWRpY3RvcmFzLA0KIyAgbWllbnRyYXMgcXVlIHBhcmEgbG9zIGNvbmp1bnRvcyB0cmFpbi4yIHkgdHJhaW4uMyB1bmljYW1lbnRlIGFwYXJlY2UgZWwgbW9kZWxvIHRhc3RlIH4gSDJTICsgTGFjdGljLg0KbW9kZWwuMWNyaXQgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGE9Y2hlZGRhclt0cmFpbi4xLF0pDQoNCiMgRXN0byBub3MgcHVlZGUgbGxldmFyIGEgcGVuc2FyIHF1ZSBlbCBtb2RlbG8gZmluYWwgdmF5YSBhIHNlciBlbCBxdWUgdXRpbGl6YSBIMlMgeSBMYWN0aWMuDQoNCm1vZGVsLjENCm1vZGVsLjFjcml0DQptb2RlbC4yDQptb2RlbC4zDQoNCmFub3ZhKG1vZGVsLjEsbW9kZWwuYWxsMSkNCmFub3ZhKG1vZGVsLjFjcml0LG1vZGVsLmFsbDEpDQphbm92YShtb2RlbC4yLG1vZGVsLmFsbDIpDQphbm92YShtb2RlbC4zLG1vZGVsLmFsbDMpDQojIERlIGVzdGEgZm9ybWEgdmVtb3MgcXVlIGxvcyBtb2RlbG9zIGNyZWFkb3Mgc29uIG1lam9yZXMgcXVlIGxvcyBjb21wbGV0b3MuDQoNCg0KDQoNCg0KIyA0KSBEaWFnbm9zdGljby4gQ29tcHJvYmFjaW9uZXMgZGUgaGlwb3Rlc2lzLCBvdXRsaWVycyB5IG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMNCg0KIyBDb21wcm9iYWNpb24gZGUgaGlwb3Rlc2lzIGRlIGxvcyAgbW9kZWxvcw0KDQojIExpbmVhbGlkYWQNCg0KcmVzZXR0ZXN0KG1vZGVsLjEsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjEsXSkNCnJlc2V0dGVzdChtb2RlbC4xY3JpdCwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMSxdKQ0KcmVzZXR0ZXN0KG1vZGVsLjIsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjIsXSkNCnJlc2V0dGVzdChtb2RlbC4zLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4zLF0pDQojIHAtdmFsb3JlcyA+IDAuMDUgbHVlZ28gYWNlcHRhbW9zIGhpcMOzdGVzaXMgZGUgbGluZWFsaWRhZCBlbiB0b2RvcyBsb3MgY2Fzb3MNCg0KcGxvdChjaGVkZGFyJEgyUywgY2hlZGRhciR0YXN0ZSwNCiAgICAgbWFpbiA9ICJSZWxhY2lvbiBlbnRyZSBUYXN0ZSB5IEgyUyIsDQogICAgIHhsYWIgPSAiSDJTIiwgeWxhYiA9ICJUYXN0ZSIsDQogICAgIHBjaCA9IDE5LCBmcmFtZSA9IEZBTFNFKQ0KcGxvdChjaGVkZGFyJExhY3RpYywgY2hlZGRhciR0YXN0ZSwNCiAgICAgbWFpbiA9ICJSZWxhY2lvbiBlbnRyZSBUYXN0ZSB5IExhY3RpYyIsDQogICAgIHhsYWIgPSAiTGFjdGljIiwgeWxhYiA9ICJUYXN0ZSIsDQogICAgIHBjaCA9IDE5LCBmcmFtZSA9IEZBTFNFKQ0KDQoNCg0KIyBOb3JtYWxpZGFkIHkgQXV0b2NvcnJlbGFjaW9uDQoNCnNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xKSkgIyBwLXZhbG9yID4gMC4wNSBubyBzZSByZWNoYXphIGxhIGhpcMOzdGVzaXMgbnVsYSwgaS5lLiBsYSBub3JtYWxpZGFkDQpxcW5vcm0ocmVzaWQobW9kZWwuMSkpDQpxcWxpbmUocmVzaWQobW9kZWwuMSkpDQoNCnNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xY3JpdCkpI2JpZW4NCnFxbm9ybShyZXNpZChtb2RlbC4xY3JpdCkpDQpxcWxpbmUocmVzaWQobW9kZWwuMWNyaXQpKQ0KDQpzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMikpI2JpZW4NCnFxbm9ybShyZXNpZChtb2RlbC4yKSkNCnFxbGluZShyZXNpZChtb2RlbC4yKSkNCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjMpKSNiaWVuDQpxcW5vcm0ocmVzaWQobW9kZWwuMykpDQpxcWxpbmUocmVzaWQobW9kZWwuMykpDQoNCiMgT2JzZXJ2YW1vcyBxdWUgbGFzIGNvbGFzIG5vIHNpZ3VlbiBlbCBtaXNtbyBwYXRyw7NuIHF1ZSBlbCByZXN0byBkZSBkYXRvcywgbG8gcXVlIHBvZHLDrWEgaW5kaWNhciBxdWUNCiMgIGVsIG1vZGVsbyBubyBzaWd1ZSB1bmEgZGlzdHJpYnVjacOzbiBub3JtYWwuIFNpbiBlbWJhcmdvLCBhbCBubyBhZmVjdGFyIGEgdW4gZ3JhbiBwb3JjZW50YWplIGRlIGxvcyBkYXRvcyB5DQojICB0ZW5pZW5kbyBlbiBjdWVudGEgZWwgcmVzdWx0YWRvIHByZXZpbyBvYnRlbmlkbyBwb3IgZWwgVGVzdCBkZSBTaGFwaXJvLVdpbGsgbm8gcmVjaGF6YW1vcyBsYSBoaXDDs3Rlc2lzIGRlIG5vcm1hbGlkYWQuDQoNCg0KIyBNZWRpYSBkZSBlcnJvcmVzIG51bGENCg0KdC50ZXN0KHJlc2lkKG1vZGVsLjEpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpDQp0LnRlc3QocmVzaWQobW9kZWwuMWNyaXQpLCBtdSA9IDAsIGFsdGVybmF0aXZlID0gInR3by5zaWRlZCIpDQp0LnRlc3QocmVzaWQobW9kZWwuMiksIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikNCnQudGVzdChyZXNpZChtb2RlbC4zKSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKQ0KIyBwLXZhbG9yZXMgfiAxID4gMC4wNSBsdWVnbyBhY2VwdGFtb3MgbGEgaGlwb3Rlc2lzIG51bGEgZW4gdG9kb3MgbG9zIGNhc29zDQoNCg0KDQojIEF1dG9jb3JyZWxhY2lvbg0KDQpkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjEpDQpkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjFjcml0KQ0KZHVyYmluV2F0c29uVGVzdChtb2RlbC4yKQ0KZHVyYmluV2F0c29uVGVzdChtb2RlbC4zKQ0KIyBwLXZhbG9yZXMgPiAwLjA1IGx1ZWdvIHJlY2hhemFtb3MgcXVlIGhheWEgYXV0b2NvcnJlbGFjaW9uDQoNCg0KDQojIEhvbW9jZWRhc3RpY2lkYWQNCg0KZm1vZGVsMSA8LSBmb3J0aWZ5KG1vZGVsLjEpDQpmbW9kZWwxY3JpdCA8LSBmb3J0aWZ5KG1vZGVsLjFjcml0KQ0KZm1vZGVsMiA8LSBmb3J0aWZ5KG1vZGVsLjIpDQpmbW9kZWwzIDwtIGZvcnRpZnkobW9kZWwuMykNCg0KWDEgPC0gZm1vZGVsMSQuZml0dGVkDQpZMSA8LSBmbW9kZWwxJC5zdGRyZXNpZA0KDQpYMWNyaXQgPC0gZm1vZGVsMWNyaXQkLmZpdHRlZA0KWTFjcml0IDwtIGZtb2RlbDFjcml0JC5zdGRyZXNpZA0KDQpYMiA8LSBmbW9kZWwyJC5maXR0ZWQNClkyIDwtIGZtb2RlbDIkLnN0ZHJlc2lkDQoNClgzIDwtIGZtb2RlbDMkLmZpdHRlZA0KWTMgPC0gZm1vZGVsMyQuc3RkcmVzaWQNCg0KcGxvdChYMSwgWTEsIHlsYWIgPSAiUmVzaWR1b3MgZXN0YW5kYXJpemFkb3MiLCB4bGFiID0gInZhbG9yZXMgYWp1c3RhZG9zIikNCnBsb3QoWDFjcml0LCBZMWNyaXQsIHlsYWIgPSAiUmVzaWR1b3MgZXN0YW5kYXJpemFkb3MiLCB4bGFiID0gInZhbG9yZXMgYWp1c3RhZG9zIikNCnBsb3QoWDIsIFkyLCB5bGFiID0gIlJlc2lkdW9zIGVzdGFuZGFyaXphZG9zIiwgeGxhYiA9ICJ2YWxvcmVzIGFqdXN0YWRvcyIpI2Nhc2kgY2FzaSBoYXkgcGF0cm9uDQpwbG90KFgzLCBZMywgeWxhYiA9ICJSZXNpZHVvcyBlc3RhbmRhcml6YWRvcyIsIHhsYWIgPSAidmFsb3JlcyBhanVzdGFkb3MiKQ0KIyBMb3MgcmVzaWR1b3Mgc2UgZGlzdHJpYnV5ZW4gZGUgZm9ybWEgaG9tb2fDqW5lYSBhIGxvIGxhcmdvIGRlIHVuYSBiYW5kYSBob3Jpem9udGFsLCBsdWVnbyBzZSB2ZXJpZmljYSBsYSBoaXDDs3Rlc2lzIG51bGENCg0KDQpuY3ZUZXN0KG1vZGVsLjEpDQpuY3ZUZXN0KG1vZGVsLjFjcml0KQ0KbmN2VGVzdChtb2RlbC4yKQ0KbmN2VGVzdChtb2RlbC4zKQ0KIyBwLXZhbG9yZXMgPiAwLjA1LCBsdWVnbyBubyBoYXkgZXZpZGVuY2lhIHBhcmEgcmVjaGF6YXIgcXVlIGxhIHZhcmlhbnphIHNlYSBjb25zdGFudGUNCg0KDQoNCiMgT3V0bGllcnMNCg0KYWxwaGEgPC0gMC4wNQ0KbjEgPC0gbnJvdyhjaGVkZGFyW3RyYWluLjEsXSkNCnAxIDwtIG5yb3coc3VtbWFyeShtb2RlbC4xKSRjb2VmKQ0KDQpuMWNyaXQgPC0gbnJvdyhjaGVkZGFyW3RyYWluLjEsXSkNCnAxY3JpdCA8LSBucm93KHN1bW1hcnkobW9kZWwuMWNyaXQpJGNvZWYpDQoNCm4yIDwtIG5yb3coY2hlZGRhclt0cmFpbi4yLF0pDQpwMiA8LSBucm93KHN1bW1hcnkobW9kZWwuMikkY29lZikNCg0KbjMgPC0gbnJvdyhjaGVkZGFyW3RyYWluLjMsXSkNCnAzIDwtIG5yb3coc3VtbWFyeShtb2RlbC4zKSRjb2VmKQ0KDQoNCiMgRWwgdmFsb3IgY3JpdGljbyBkZSBCb25mZXJyb25pIHRfezEtYWxwaGEvMm47bi1wLTF9DQpCQ1YxIDwtIHF0KDEgLSBhbHBoYSAvICgyICogbjEpLCBuMS1wMS0xKQ0KQkNWMWNyaXQgPC0gcXQoMSAtIGFscGhhIC8gKDIgKiBuMWNyaXQpLCBuMWNyaXQtcDFjcml0LTEpDQpCQ1YyIDwtIHF0KDEgLSBhbHBoYSAvICgyICogbjIpLCBuMi1wMi0xKQ0KQkNWMyA8LSBxdCgxIC0gYWxwaGEgLyAoMiAqIG4zKSwgbjMtcDMtMSkNCg0Kc3VtKGFicyhyc3R1ZGVudChtb2RlbC4xKSkgPiBCQ1YxKQ0Kc3VtKGFicyhyc3R1ZGVudChtb2RlbC4xY3JpdCkpID4gQkNWMWNyaXQpDQpzdW0oYWJzKHJzdHVkZW50KG1vZGVsLjIpKSA+IEJDVjIpDQpzdW0oYWJzKHJzdHVkZW50KG1vZGVsLjMpKSA+IEJDVjMpDQoNCm91dGxpZXJUZXN0KG1vZGVsLjEpI05BPw0Kb3V0bGllclRlc3QobW9kZWwuMWNyaXQpICNOQT8NCm91dGxpZXJUZXN0KG1vZGVsLjIpDQpvdXRsaWVyVGVzdChtb2RlbC4zKQ0KIyBObyBoYXkgb3V0bGllcnMgZW4gbmluZ3VubyBkZSBsb3MgZG9zIG1vZGVsb3MgcGxhbnRlYWRvcw0KDQoNCg0KIyBPYnNlcnZhY2lvbmVzIEluZmx1eWVudGVzDQoNCiMgQ3JpdGVyaW8gMTogdmFsb3JlcyBsZXZlcmFnZSAoaGlpKSBtYXlvcmVzIHF1ZSAycC9uDQoNClgxIDwtIG1vZGVsLm1hdHJpeCh+IEgyUytMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjEsXSkNClgxY3JpdCA8LSBtb2RlbC5tYXRyaXgofiBIMlMrTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xLF0pDQpYMiA8LSBtb2RlbC5tYXRyaXgofiBIMlMrTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4yLF0pDQpYMyA8LSBtb2RlbC5tYXRyaXgofiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjMsXSkNCg0KSDEgPC0gWDEgJSolIHNvbHZlKHQoWDEpICUqJSBYMSkgJSolIHQoWDEpDQpIMWNyaXQgPC0gWDFjcml0ICUqJSBzb2x2ZSh0KFgxY3JpdCkgJSolIFgxY3JpdCkgJSolIHQoWDFjcml0KQ0KSDIgPC0gWDIgJSolIHNvbHZlKHQoWDIpICUqJSBYMikgJSolIHQoWDIpDQpIMyA8LSBYMyAlKiUgc29sdmUodChYMykgJSolIFgzKSAlKiUgdChYMykNCg0KaGlpMSA8LSBkaWFnKEgxKQ0KaGlpMWNyaXQgPC0gZGlhZyhIMWNyaXQpDQpoaWkyIDwtIGRpYWcoSDIpDQpoaWkzIDwtIGRpYWcoSDMpDQoNCmhDVjEgPC0gMiAqIHAxIC8gbjENCmhDVjFjcml0IDwtIDIgKiBwMWNyaXQgLyBuMWNyaXQNCmhDVjIgPC0gMiAqIHAyIC8gbjINCmhDVjMgPC0gMiAqIHAzIC8gbjMNCg0Kc3VtKGhpaTEgPiBoQ1YxKQ0Kd2hpY2goaGlpMT5oQ1YxKSMxICA1IDE2IDIzIDI0IDI2DQoNCnN1bShoaWkxY3JpdCA+IGhDVjFjcml0KQ0Kd2hpY2goaGlpMWNyaXQ+aENWMWNyaXQpDQoNCnN1bShoaWkyID4gaENWMikNCndoaWNoKGhpaTI+aENWMikNCg0Kc3VtKGhpaTMgPiBoQ1YzKQ0KDQoNCiMgQ3JpdGVyaW8gMjogdmFsb3JlcyB8REZGSVRTfCBzb24gbWF5b3JlcyBxdWUgMipzcXJ0KHAvbikNCg0KZGZmaXRzQ1YxIDwtIDIgKiBzcXJ0KHAxIC8gbjEpDQpkZmZpdHNDVjFjcml0IDwtIDIgKiBzcXJ0KHAxY3JpdCAvIG4xY3JpdCkNCmRmZml0c0NWMiA8LSAyICogc3FydChwMiAvIG4yKQ0KZGZmaXRzQ1YzIDwtIDIgKiBzcXJ0KHAzIC8gbjMpDQoNCmRmZml0c21vZGVsMSA8LSBkZmZpdHMobW9kZWwuMSkNCmRmZml0c21vZGVsMWNyaXQgPC0gZGZmaXRzKG1vZGVsLjFjcml0KQ0KZGZmaXRzbW9kZWwyIDwtIGRmZml0cyhtb2RlbC4yKQ0KZGZmaXRzbW9kZWwzIDwtIGRmZml0cyhtb2RlbC4zKQ0KDQpzdW0oZGZmaXRzbW9kZWwxID4gZGZmaXRzQ1YxKQ0Kd2hpY2goZGZmaXRzbW9kZWwxID4gZGZmaXRzQ1YxKSMxIDEyIDI0DQoNCnN1bShkZmZpdHNtb2RlbDFjcml0ID4gZGZmaXRzQ1YxY3JpdCkNCndoaWNoKGRmZml0c21vZGVsMWNyaXQgPiBkZmZpdHNDVjFjcml0KSMxLCAxMg0KDQpzdW0oZGZmaXRzbW9kZWwyID4gZGZmaXRzQ1YyKQ0Kc3VtKGRmZml0c21vZGVsMyA+IGRmZml0c0NWMykNCg0KDQoNCiMgQ3JpdGVyaW8gMzogdmFsb3JlcyB8REZCRVRBU3wgbWF5b3JlcyBxdWUgMi9zcXJ0KG4pDQoNCmRmYmV0YUNWMSA8LSAyIC8gc3FydChuMSkNCmRmYmV0YUNWMWNyaXQgPC0gMiAvIHNxcnQobjFjcml0KQ0KZGZiZXRhQ1YyIDwtIDIgLyBzcXJ0KG4yKQ0KZGZiZXRhQ1YzIDwtIDIgLyBzcXJ0KG4zKQ0KDQpkZmJldGFtb2RlbDEgPC0gZGZiZXRhKG1vZGVsLjEpDQpkZmJldGFtb2RlbDFjcml0IDwtIGRmYmV0YShtb2RlbC4xY3JpdCkNCmRmYmV0YW1vZGVsMiA8LSBkZmJldGEobW9kZWwuMikNCmRmYmV0YW1vZGVsMyA8LSBkZmJldGEobW9kZWwuMykNCg0KDQpzdW0oZGZiZXRhbW9kZWwxWywgMV0gPiBkZmJldGFDVjEpDQpzdW0oZGZiZXRhbW9kZWwxWywgMl0gPiBkZmJldGFDVjEpDQp3aGljaChkZmJldGFtb2RlbDFbLCAxXSA+IGRmYmV0YUNWMSkNCndoaWNoKGRmYmV0YW1vZGVsMVssIDJdID4gZGZiZXRhQ1YxKQ0KDQpzdW0oZGZiZXRhbW9kZWwxY3JpdFssIDFdID4gZGZiZXRhQ1YxY3JpdCkNCnN1bShkZmJldGFtb2RlbDFjcml0WywgMl0gPiBkZmJldGFDVjFjcml0KQ0Kc3VtKGRmYmV0YW1vZGVsMWNyaXRbLCAzXSA+IGRmYmV0YUNWMWNyaXQpDQp3aGljaChkZmJldGFtb2RlbDFjcml0WywgMV0gPiBkZmJldGFDVjFjcml0KQ0Kd2hpY2goZGZiZXRhbW9kZWwxY3JpdFssIDNdID4gZGZiZXRhQ1YxY3JpdCkNCg0Kc3VtKGRmYmV0YW1vZGVsMlssIDFdID4gZGZiZXRhQ1YyKQ0Kc3VtKGRmYmV0YW1vZGVsMlssIDJdID4gZGZiZXRhQ1YyKQ0Kc3VtKGRmYmV0YW1vZGVsMlssIDNdID4gZGZiZXRhQ1YyKQ0Kd2hpY2goZGZiZXRhbW9kZWwyWywgMV0gPiBkZmJldGFDVjIpDQp3aGljaChkZmJldGFtb2RlbDJbLCAzXSA+IGRmYmV0YUNWMikNCg0Kc3VtKGRmYmV0YW1vZGVsM1ssIDFdID4gZGZiZXRhQ1YzKQ0Kc3VtKGRmYmV0YW1vZGVsM1ssIDJdID4gZGZiZXRhQ1YzKQ0Kc3VtKGRmYmV0YW1vZGVsM1ssIDNdID4gZGZiZXRhQ1YzKQ0Kd2hpY2goZGZiZXRhbW9kZWwzWywgMV0gPiBkZmJldGFDVjMpDQp3aGljaChkZmJldGFtb2RlbDNbLCAzXSA+IGRmYmV0YUNWMykNCg0KIyBEYWRvIHF1ZSBudWVzdHJvIGRhdHNldCBlcyBwZXF1ZcOxbywgbm8gdGVuZHJlbXNvIGVuIGN1ZW50YSBlc3RlIG1ldG9kbyBwb3IgZGFyIGRlbWFzaWFkYXMgb2JzZXJ2YWNpb25lcy4NCg0KDQojIEdyYWZpY2EgY29uIGxhcyBkaXN0YW5jaWFzIGRlIENvb2sNCmluZmx1ZW5jZVBsb3QobW9kZWwuMSkNCnBvc19pbmZsdXllbnRlc18xIDwtIGMoMSwxMiwyNCkNCg0KaW5mbHVlbmNlUGxvdChtb2RlbC4xY3JpdCkNCnBvc19pbmZsdXllbnRlc18xY3JpdCA8LSBjKDEsOCwxMiwyMykNCg0KaW5mbHVlbmNlUGxvdChtb2RlbC4yKQ0KcG9zX2luZmx1eWVudGVzXzIgPC0gYygxLDYsNyw4LDE1KQ0KDQppbmZsdWVuY2VQbG90KG1vZGVsLjMpDQpwb3NfaW5mbHV5ZW50ZXNfMyA8LSBjKDEsNywxNSwxOSwyNCkNCg0KDQoNCiMgQ29saW5lYWxpZGFkDQp2aWYobW9kZWwuMSkgIyB0aWVuZSBzZW50aWRvIHB1ZXMgZW4gbW9kZWwuMSBzb2xvIGhheSB1bmEgdmFyaWFibGUgcHJlZGljdG9yYQ0KdmlmKG1vZGVsLjFjcml0KQ0KdmlmKG1vZGVsLjIpDQp2aWYobW9kZWwuMykgIyBjb21vIGxvcyB2YWxvcmVzIGRlIFZJRiBubyBzb24gZ3JhbmRvLCBubyBpbmRpY2FuIGNvbGluZWFsaWRhZCBncmF2ZQ0KDQoNCiMgVmFtb3MgYSB0b21hciBjb21vIHBvc2libGVzIGluZmx1eWVudGVzIGxhcyBxdWUgYXBhcmVjZW4gcG9yIHZhcmlvcyBtZXRvZG9zIGVuIGNhZGEgbW9kZWxvDQoNCiMgRW4gZWwgMTogMSAxMg0KcG9zXzEgPC0gYyhUUlVFLHJlcChGQUxTRSwxMCksVFJVRSxyZXAoRkFMU0UsMTgpKQ0KdHJhaW4uMWluZiA8LSB0cmFpbi4xJiFwb3NfMQ0KbW9kZWwuMWluZiA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMWluZixdKQ0KDQpuY3ZUZXN0KG1vZGVsLjEpDQpuY3ZUZXN0KG1vZGVsLjFpbmYpICMgZW1wZW9yYSBwZXJvIHNpZ3VlIGN1bXBsaWVuZG8gbGEgaGlwb3Rlc2lzDQoNCnNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xKSkNCnNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xaW5mKSkgIyBtZWpvcmEgcG9jbw0KDQpkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjEpDQpkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjFpbmYpICMgbWVqb3JhDQoNCnJlc2V0dGVzdChtb2RlbC4xLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4xaW5mLF0pDQpyZXNldHRlc3QobW9kZWwuMWluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMWluZixdKSAjIG1lam9yYSBiYXN0YW50ZQ0KDQojIFJlZGVmaW5pbW9zIGVsIG1vZGVsbyBlbGltaW5hbmRvIGxhcyBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIGRlIHBvc18xLg0KdHJhaW4uMWF1eDwtdHJhaW4uMQ0KdHJhaW4uMSA8LSB0cmFpbi4xaW5mDQptb2RlbC4xIDwtIG1vZGVsLjFpbmYNCg0KDQojIEVuIGVsIDFjcml0OiAxIDEyICAyMw0KcG9zXzFjcml0IDwtIGMoVFJVRSxyZXAoRkFMU0UsMTApLFRSVUUscmVwKEZBTFNFLDEwKSxUUlVFLHJlcChGQUxTRSw3KSkNCnRyYWluLjFjcml0aW5mIDwtIHRyYWluLjEmIXBvc18xY3JpdA0KbW9kZWwuMWNyaXRpbmYgPC0gbG0odGFzdGUgfkgyUytMYWN0aWMgLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xY3JpdGluZixdKQ0KDQpuY3ZUZXN0KG1vZGVsLjFjcml0KQ0KbmN2VGVzdChtb2RlbC4xY3JpdGluZikgIyBlbXBlb3JhDQoNCnNoYXBpcm8udGVzdChyZXNpZChtb2RlbC4xY3JpdCkpDQpzaGFwaXJvLnRlc3QocmVzaWQobW9kZWwuMWNyaXRpbmYpKSAjIG1lam9yYQ0KDQpkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjFjcml0KQ0KZHVyYmluV2F0c29uVGVzdChtb2RlbC4xY3JpdGluZikgIyBtZWpvcmEgYmFzdGFudGUNCg0KcmVzZXR0ZXN0KG1vZGVsLjFjcml0LCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4xLF0pDQpyZXNldHRlc3QobW9kZWwuMWNyaXRpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjFjcml0aW5mLF0pICMgZW1wZW9yYSBkZW50cm8gZGUgYWNlcHRhYmxlDQoNCiMgUmVkZWZpbmltb3MgZWwgbW9kZWxvIGVsaW1pbmFuZG8gbGFzIG9ic2VydmFjaW9uZXMgaW5mbHV5ZW50ZXMgZGUgcG9zXzFjcml0Lg0KdHJhaW4uMWNyaXQgPC0gdHJhaW4uMWNyaXRpbmYNCm1vZGVsLjFjcml0IDwtIG1vZGVsLjFjcml0aW5mDQoNCg0KIyBFbiBlbCAyOiA2DQpwb3NfMiA8LSBjKHJlcChGQUxTRSw1KSxUUlVFLHJlcChGQUxTRSwyNCkpDQp0cmFpbi4yaW5mIDwtIHRyYWluLjImIXBvc18yDQptb2RlbC4yaW5mIDwtIGxtKHRhc3RlIH4gSDJTK0xhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMmluZixdKQ0KDQpuY3ZUZXN0KG1vZGVsLjIpDQpuY3ZUZXN0KG1vZGVsLjJpbmYpICMgbWVqb3JhIHBvY28NCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjIpKQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLjJpbmYpKSAjIGFwcm94aW1hZGFtZW50ZSBsbyBtaXNtbw0KDQpkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjIpDQpkdXJiaW5XYXRzb25UZXN0KG1vZGVsLjJpbmYpICMgbWVqb3JhDQoNCnJlc2V0dGVzdChtb2RlbC4yLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4yaW5mLF0pDQpyZXNldHRlc3QobW9kZWwuMmluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uMmluZixdKSAjIGFwcm94aW1hZGFtZW50ZSBsbyBtaXNtbw0KDQojIFJlZGVmaW5pbW9zIGVsIG1vZGVsbyBlbGltaW5hbmRvIGxhcyBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIGRlIHBvc18yLg0KdHJhaW4uMiA8LSB0cmFpbi4yaW5mDQptb2RlbC4yIDwtIG1vZGVsLjJpbmYNCg0KDQojIEVuIGVsIG1vZGVsbyAzIG5vIGhhY2Vtb3MgY29tcHJvYmFjaW9uZXMgbmFkYSB5YSBxdWUgbm8gc2UgcmVwaXRlbiBvYnNlcnZhY2lvbmVzIHBvciBkaXN0aW50b3MgbWV0b2Rvcy4NCg0KDQoNCg0KDQojIDUpIEVycm9yZXMgZGUgVGVzdC4gQ29tcGFyYWNpb24gZGUgTW9kZWxvcw0KDQojIFZhbW9zIGEgY29uc2lkZXJhciBvdHJhcyBkb3Mgc2VtaWxsYXMgcGFyYSBldmFsdWFyIGxvcyBtb2RlbG9zIHkgZWxlZ2lyIGVsIG1lam9yLg0KIyBMYXMgdG9tYW1vcyBkZSBmb3JtYSBxdWUgbm8gY29pbmNpZGFuIGVuIGxhIG1lZGlkYSBkZSBsbyBwb3NpYmxlIGxvcyB0ZXN0cyBkZSBsYXMgZGlzdGludGFzIHBhcnRpY2lvbmVzLg0KIyBEaXZpZGltb3MgZWwgY29uanVudG8gdG90YWwgcGFyYSBsYXMgZG9zIHNlbWlsbGFzIG51ZXZhcy4NCg0Kc2V0LnNlZWQoKDIyMzQpKQ0KdHJhaW4uNCA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KdGVzdC40IDwtICghdHJhaW4uNCkNCnN1bSh0ZXN0LjQpDQpzdW0odGVzdC4xPT1UUlVFICYgdGVzdC40PT1UUlVFKQ0Kc3VtKHRlc3QuMj09VFJVRSAmIHRlc3QuND09VFJVRSkNCnN1bSh0ZXN0LjM9PVRSVUUgJiB0ZXN0LjQ9PVRSVUUpDQoNCg0Kc2V0LnNlZWQoKDEzMSkpDQp0cmFpbi41IDwtIHNhbXBsZShjKFRSVUUsIEZBTFNFKSwgc2l6ZSA9IG5yb3coY2hlZGRhciksIHJlcGxhY2UgPSBUUlVFLCBwcm9iID0gYygwLjcsIDAuMykpDQp0ZXN0LjUgPC0gKCF0cmFpbi41KQ0Kc3VtKHRlc3QuNSkNCnN1bSh0ZXN0LjE9PVRSVUUgJiB0ZXN0LjU9PVRSVUUpDQpzdW0odGVzdC4yPT1UUlVFICYgdGVzdC41PT1UUlVFKQ0Kc3VtKHRlc3QuMz09VFJVRSAmIHRlc3QuNT09VFJVRSkNCnN1bSh0ZXN0LjQ9PVRSVUUgJiB0ZXN0LjU9PVRSVUUpDQoNCnRyYWluLjFoIDwtIHRyYWluLjFjcml0DQp0cmFpbi4yaCA8LSB0cmFpbi4yDQp0cmFpbi4zaCA8LSB0cmFpbi4zDQp0cmFpbi40aCA8LSB0cmFpbi40DQp0cmFpbi41aCA8LSB0cmFpbi41DQoNCiMgUmVjYWxjdWxhbW9zIHRyYWluLjIgcG9ycXVlIGZ1ZSBtb2RpZmljYWRvDQpzZXQuc2VlZCgxMTAwKQ0KdHJhaW4uMiA8LSBzYW1wbGUoYyhUUlVFLCBGQUxTRSksIHNpemUgPSBucm93KGNoZWRkYXIpLCByZXBsYWNlID0gVFJVRSwgcHJvYiA9IGMoMC43LCAwLjMpKQ0KDQoNCg0KDQojIFZlYW1zbyBzaSBwb2RlbW9zIGVsaW1pbmFyIHBvc2libGVzIGluZmx1eWVudGVzIGVuIGxvcyBtb2RlbG9zIHJlc3RhbnRlcw0KDQptaDEgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjFoLF0pICMgY29tcHJvYmFkb3Mgc3VwdWVzdG9zDQptaDIgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjJoLF0pICMgY29tcHJvYmFkb3Mgc3VwdWVzdG9zDQptaDMgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjNoLF0pICMgY29tcHJvYmFkb3Mgc3VwdWVzdG9zDQptaDQgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjRoLF0pDQptaDUgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjVoLF0pDQoNCm0xIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi4xLF0pICMgY29tcHJvYmFkb3Mgc3VwdWVzdG9zDQptMiA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uMixdKQ0KbTMgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjMsXSkNCm00IDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi40LF0pDQptNSA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uNSxdKQ0KDQoNCiMgQWwgaWd1YWwgcXVlIGhpY2ltb3MgZW4gNCBjb21wcm9iYW1vcyBzaSByZXRpcmFuZG8gb3V0bGllcnMgeSBvYnNlcnZhY2lvbmVzIGluZmx1eWVudGVzIG1lam9yYW4gbGFzIGhpcG90ZXNpcy4NCiMgIFVuaWNhbWVudGUgY29uc2lkZXJhcmVtb3Mgb2JzZXJ2YWNpb25lcyBvYnRlbmlkYXMgdGFudG8gcG9yIG91dGxpZXJUZXN0KCkgY29tbyBwb3IgaW5mbHVlbmNlUGxvdCgpLg0KDQojIG1oNA0Kb3V0bGllclRlc3QobWg0KQ0KaW5mbHVlbmNlUGxvdChtaDQpICMgNiwxMiwxNSwyNA0KcG9zNGggPC0gYyhyZXAoRkFMU0UsNSksVFJVRSxyZXAoRkFMU0UsNSksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsOCksVFJVRSxyZXAoRkFMU0UsNikpDQoNCnRyYWluLjRpbmYgPC0gdHJhaW4uNGgmIXBvczRoDQptaDRpbmYgPC0gbG0odGFzdGUgfiBIMlMrTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi40aW5mLF0pDQoNCm5jdlRlc3QobWg0KQ0KbmN2VGVzdChtaDRpbmYpICMgbWVqb3JhIE1VQ0hPDQoNCnNoYXBpcm8udGVzdChyZXNpZChtaDQpKQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG1oNGluZikpICMgbWVqb3JhDQoNCmR1cmJpbldhdHNvblRlc3QobWg0KQ0KZHVyYmluV2F0c29uVGVzdChtaDRpbmYpICMgbWVqb3JhDQoNCnJlc2V0dGVzdChtaDQsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjRpbmYsXSkNCnJlc2V0dGVzdChtaDRpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjRpbmYsXSkgIyBlbXBlb3JhIHBlcm8gZXMgYWNlcHRhYmxlDQoNCiMgUmVkZWZpbmltb3MgZWxpbWluYW5kbyBwb3M0aCBwb3Igc2VyIHRhbnRhIGxhIG1lam9yYSBlbiBob21vY2VkYXN0aWNpZGFkIHF1ZSBjb21wZW5zYSBsYSBsaW5lYWxpZGFkDQp0cmFpbi40aCA8LSB0cmFpbi40aW5mDQptaDQgPC0gbWg0aW5mDQoNCg0KIyBtaDUNCm91dGxpZXJUZXN0KG1oNSkNCmluZmx1ZW5jZVBsb3QobWg1KSAjIDYsNyw4LDEyLDE1DQpwb3M1aCA8LSBjKHJlcChGQUxTRSw1KSxUUlVFLFRSVUUsVFJVRSxyZXAoRkFMU0UsMyksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsMTUpKQ0KDQp0cmFpbi41aW5mIDwtIHRyYWluLjVoJiFwb3M1aA0KbWg1aW5mIDwtIGxtKHRhc3RlIH4gSDJTK0xhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uNWluZixdKQ0KDQpuY3ZUZXN0KG1oNSkNCm5jdlRlc3QobWg1aW5mKSAjIG1lam9yYQ0KDQpzaGFwaXJvLnRlc3QocmVzaWQobWg1KSkNCnNoYXBpcm8udGVzdChyZXNpZChtaDVpbmYpKSAjIGVtcGVvcmENCg0KZHVyYmluV2F0c29uVGVzdChtaDUpDQpkdXJiaW5XYXRzb25UZXN0KG1oNWluZikgIyBhIHZlY2VzIG5vIHNlIGN1bXBsZSBsYSBoaXBvdGVzaXMgbnVsYSBkZSBubyBhdXRvY29ycmVsYWNpb24NCg0KcmVzZXR0ZXN0KG1oNSwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNWluZixdKQ0KcmVzZXR0ZXN0KG1oNWluZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNWluZixdKSAjIGVtcGVvcmENCg0KIyBEZWNpZGltb3Mgbm8gYWN0dWFsaXphciBlbCBtb2RlbG8gcHVlcyBubyBzaWVtcHJlIHNlIHJlY2hhemEgbGEgY29ycmVsYWNpb24geSBlbXBlb3JhbiBvdHJvcyBwLXZhbG9yZXMuDQoNCg0KIyBtMg0Kb3V0bGllclRlc3QobTIpDQppbmZsdWVuY2VQbG90KG0yKSAjIDEsMTIsMTUsMTgsMjQNCnBvczIgPC0gYyhUUlVFLHJlcChGQUxTRSwxMCksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsNSksVFJVRSxyZXAoRkFMU0UsNikpDQoNCnRyYWluLjJpbmYgPC0gdHJhaW4uMiYhcG9zMg0KbTJpbmYgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjJpbmYsXSkNCg0KbmN2VGVzdChtMikNCm5jdlRlc3QobTJpbmYpICMgZW1wZW9yYSBsaWdlcmFtZW50ZQ0KDQpzaGFwaXJvLnRlc3QocmVzaWQobTIpKQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG0yaW5mKSkgIyBlbXBlb3JhIGxpZ2VyYW1lbnRlDQoNCmR1cmJpbldhdHNvblRlc3QobTIpDQpkdXJiaW5XYXRzb25UZXN0KG0yaW5mKSAjIGVtcGVvcmEgYmFzdGFudGUNCg0KcmVzZXR0ZXN0KG0yLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi4yaW5mLF0pDQpyZXNldHRlc3QobTJpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjJpbmYsXSkgIyBtZWpvcmENCg0KIyBEZWNpY2ltb3Mgbm8gcmVkZWZpbmlybG8sIHlhIHF1ZSBlbXBlb3JhIGVuIG11Y2hhcyB5IG1lam9yYSBiYXN0YW50ZSBlbiB1bmENCg0KDQojIG0zDQpvdXRsaWVyVGVzdChtMykNCmluZmx1ZW5jZVBsb3QobTMpICMgMSwxNSwxOSwyNA0KcG9zMyA8LSBjKFRSVUUscmVwKEZBTFNFLDEzKSxUUlVFLHJlcChGQUxTRSwzKSxUUlVFLHJlcChGQUxTRSw0KSxUUlVFLHJlcChGQUxTRSw2KSkNCg0KdHJhaW4uM2luZiA8LSB0cmFpbi4zJiFwb3MzDQptM2luZiA8LSBsbSh0YXN0ZSB+IExhY3RpYywgZGF0YSA9IGNoZWRkYXJbdHJhaW4uM2luZixdKQ0KDQpuY3ZUZXN0KG0zKQ0KbmN2VGVzdChtM2luZikgIyBtZWpvcmEgcG9jbw0KDQpzaGFwaXJvLnRlc3QocmVzaWQobTMpKQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG0zaW5mKSkgIyBtZWpvcmENCg0KZHVyYmluV2F0c29uVGVzdChtMykNCmR1cmJpbldhdHNvblRlc3QobTNpbmYpICMgZW1wZW9yYQ0KDQpyZXNldHRlc3QobTMsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjNpbmYsXSkNCnJlc2V0dGVzdChtM2luZiwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uM2luZixdKSAjIGVtcGVvcmEgY2FzaSBsbyBwaWVyZGUNCg0KIyBEZWNpZGltb3Mgbm8gcmVkZWZpbmlybG8gcG9yIGVzdGFyIGFsIGJvcmRlIGVuIHVuIGNyaXRlcmlvIHkgbm8gbWVqb3JhciBtdWNobyBlbiBvdHJvcw0KDQoNCiMgbTQNCm91dGxpZXJUZXN0KG00KQ0KaW5mbHVlbmNlUGxvdChtNCkgIyA2LDEyLDE1LDIwLDI0DQpwb3M0IDwtIGMocmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDUpLFRSVUUscmVwKEZBTFNFLDIpLFRSVUUscmVwKEZBTFNFLDQpLFRSVUUscmVwKEZBTFNFLDMpLFRSVUUscmVwKEZBTFNFLDYpKQ0KDQp0cmFpbi40aW5mIDwtIHRyYWluLjQmIXBvczQNCm00aW5mIDwtIGxtKHRhc3RlIH4gTGFjdGljLCBkYXRhID0gY2hlZGRhclt0cmFpbi40aW5mLF0pDQoNCm5jdlRlc3QobTQpDQpuY3ZUZXN0KG00aW5mKSAjIGVtcGVvcmEgYmFzdGFudGUNCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG00KSkNCnNoYXBpcm8udGVzdChyZXNpZChtNGluZikpICMgZW1wZW9yYQ0KDQpkdXJiaW5XYXRzb25UZXN0KG00KQ0KZHVyYmluV2F0c29uVGVzdChtNGluZikjIGVtcGVvcmEgYmFzdGFudGUNCg0KcmVzZXR0ZXN0KG00LCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi40aW5mLF0pDQpyZXNldHRlc3QobTRpbmYsIHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyW3RyYWluLjRpbmYsXSkgIyBtZWpvcmEgYWxnbw0KDQojIERlY2lkaW1vcyBubyBjYW1iaWFybG8gcG9ycXVlIGVtcGVvcmEgZW4gY2FzaSB0b2RvLCB5IGRlIHBvciBzaSB0ZW5pYSBidWVub3MgcC12YWx1ZXMNCg0KDQojIG01DQpvdXRsaWVyVGVzdChtNSkNCmluZmx1ZW5jZVBsb3QobTUpICMgMSw4LDEyLDE1LDE4LDI0DQpwb3M1IDwtIGMoVFJVRSxyZXAoRkFMU0UsNiksVFJVRSxyZXAoRkFMU0UsMyksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsMiksVFJVRSxyZXAoRkFMU0UsNSksVFJVRSxyZXAoRkFMU0UsNikpDQoNCnRyYWluLjVpbmYgPC0gdHJhaW4uNSYhcG9zNQ0KbTVpbmYgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW3RyYWluLjVpbmYsXSkNCg0KbmN2VGVzdChtNSkNCm5jdlRlc3QobTVpbmYpICMgZW1wZW9yYSBiYXN0YW50ZQ0KDQpzaGFwaXJvLnRlc3QocmVzaWQobTUpKQ0Kc2hhcGlyby50ZXN0KHJlc2lkKG01aW5mKSkgIyBtZWpvcmENCg0KZHVyYmluV2F0c29uVGVzdChtNSkNCmR1cmJpbldhdHNvblRlc3QobTVpbmYpICMgbm8gc2UgdmVyaWZpY2EgbGEgaGlwb3Rlc2lzIG51bGEgZGUgbm8gYXV0b2NvcnJlbGFjaW9uDQoNCnJlc2V0dGVzdChtNSwgcG93ZXI9MjozLCB0eXBlPSJyZWdyZXNzb3IiLCBkYXRhPWNoZWRkYXJbdHJhaW4uNWluZixdKQ0KcmVzZXR0ZXN0KG01aW5mLCBwb3dlcj0yOjMsIHR5cGU9InJlZ3Jlc3NvciIsIGRhdGE9Y2hlZGRhclt0cmFpbi41aW5mLF0pICMgZW1wZW9yYQ0KDQojIERlY2lkaW1vcyBubyBjYW1iaWFybG8gcG9yIHBlcmRlcnNlIGxhIGNvcnJlbGFjacOzbg0KDQojIE5vdGVzZSBxdWUgZW4gbG9zIG9yaWdpbmFsZXMgc2llbXByZSBzZSBjdW1wbGlhbiBsYXMgaGlwb3Rlc2lzLCBhdW5xdWUgbm8gZXJhIG5lY2VzYXJpbyBwYXJhIGVsIHByb2Nlc28NCg0KDQoNCg0KbGlzdGFfdGVzdCA8LSBsaXN0KHRlc3QuMSx0ZXN0LjIsdGVzdC4zLHRlc3QuNCx0ZXN0LjUpDQpsaXN0YV90cmFpbmggPC0gbGlzdCh0cmFpbi4xaCx0cmFpbi4yaCx0cmFpbi4zaCx0cmFpbi40aCx0cmFpbi41aCkNCmxpc3RhX3RyYWluIDwtIGxpc3QodHJhaW4uMSx0cmFpbi4yLHRyYWluLjMsdHJhaW4uNCx0cmFpbi41KQ0KDQoNCm1vZGVsb3NfaGlwIDwtIGMoIlMxIHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMxIHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMyIHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMyIHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMzIHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlMzIHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlM0IHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlM0IHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlM1IHRhc3RlIH4gSDJzICsgTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIlM1IHRhc3RlIH4gTGFjdGljIiwNCiAgICAgICAgICAgICAgICAgIk5pdmVsIGRlIHNpZ25pZmljYWNpb24iKQ0KDQpoaXBfUkwgPC0gYygiRGlzdHJpYnVjacOzbl9ub3JtYWwiLA0KICAgICAgICAgICAgIk1lZGlhXzAiLA0KICAgICAgICAgICAgIlZhcmlhbnphX25vX2NvbnN0YW50ZSIsDQogICAgICAgICAgICAiTm9fQXV0b2NvcnJlbGFjacOzbiIpDQpwbGFjZWhvbGRlciA8LSB2ZWN0b3IobW9kZSA9ICJsb2dpY2FsIixsZW5ndGggPSAxMSkNCmRmX2hpcFJMIDwtIGRhdGEuZnJhbWUoIjAiID0gcGxhY2Vob2xkZXIsDQogICAgICAgICAgICAgICAgICAgICAgICIxIiA9IHBsYWNlaG9sZGVyLA0KICAgICAgICAgICAgICAgICAgICAgICAiMiIgPSBwbGFjZWhvbGRlciwNCiAgICAgICAgICAgICAgICAgICAgICAgIjMiID0gcGxhY2Vob2xkZXIsDQogICAgICAgICAgICAgICAgICAgICAgIHJvdy5uYW1lcyA9IG1vZGVsb3NfaGlwKQ0KDQpjb2xuYW1lcyhkZl9oaXBSTCkgPC0gaGlwX1JMDQoNCnIgPC0gMQ0KZm9yIChkdHJhaW4gaW4gbGlzdGFfdHJhaW5oKXsNCiAgbW9kZWwuSEwubG0gPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsDQogICAgICAgICAgICAgICAgICAgIGRhdGEgPSBjaGVkZGFyW2R0cmFpbixdKQ0KICByZXNpZHVvcyA8LSByZXNpZChtb2RlbC5ITC5sbSkNCiAgbmV3X3JvdyA8LSBjKCkNCg0KICBzaGFwIDwtIHJvdW5kKHNoYXBpcm8udGVzdChyZXNpZHVvcykkcC52YWx1ZSw0KQ0KICB0IDwtIHQudGVzdChyZXNpZHVvcywgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSRwLnZhbHVlDQogIHYgPC0gcm91bmQobmN2VGVzdChtb2RlbC5ITC5sbSkkcCw0KQ0KICBkdyA8LSByb3VuZChkdXJiaW5XYXRzb25UZXN0KG1vZGVsLkhMLmxtKSRwLDQpDQoNCiAgbmV3X3JvdyA9IGMoc2hhcCx0LHYsZHcpDQogIGRmX2hpcFJMW3IsXSA8LSBuZXdfcm93DQogIHIgPSByICsgMg0KfQ0KDQoNCnIgPC0gMg0KZm9yIChkdHJhaW4gaW4gbGlzdGFfdHJhaW4pew0KICBtb2RlbC5MLmxtIDwtIGxtKHRhc3RlIH5MYWN0aWMsDQogICAgICAgICAgICAgICAgICAgZGF0YSA9IGNoZWRkYXJbZHRyYWluLF0pDQogIHJlc2lkdW9zIDwtIHJlc2lkKG1vZGVsLkwubG0pDQogIG5ld19yb3cgPC0gYygpDQoNCiAgc2hhcCA8LSByb3VuZChzaGFwaXJvLnRlc3QocmVzaWR1b3MpJHAudmFsdWUsNCkNCiAgdCA8LSB0LnRlc3QocmVzaWR1b3MsIG11ID0gMCwgYWx0ZXJuYXRpdmUgPSAidHdvLnNpZGVkIikkcC52YWx1ZQ0KICB2IDwtIHJvdW5kKG5jdlRlc3QobW9kZWwuTC5sbSkkcCw0KQ0KICBkdyA8LSByb3VuZChkdXJiaW5XYXRzb25UZXN0KG1vZGVsLkwubG0pJHAsNCkNCg0KICBuZXdfcm93ID0gYyhzaGFwLHQsdixkdykNCiAgZGZfaGlwUkxbcixdIDwtIG5ld19yb3cNCiAgciA9IHIgKyAyDQp9DQpkZl9oaXBSTFsxMSxdIDwtIGMocmVwKDAuMDUsNCkpDQpkZl9oaXBSTCAjIFRvZG9zIGxvcyBtb2RlbG9zIGN1bXBsZW4gbGFzIGhpcMOzdGVzaXMNCg0KDQoNCmVycjEgPC0gMA0KZm9yIChpIGluIDUpew0KICBkdHJhaW4gPC0gbGlzdGFfdHJhaW5oW1tpXV0NCiAgZHRlc3QgPC0gbGlzdGFfdGVzdFtbaV1dDQogIGRtb2QgPC0gbG0odGFzdGUgfiBIMlMgKyBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW2R0cmFpbixdKQ0KICBZIDwtIGNoZWRkYXJbZHRlc3QsXSR0YXN0ZQ0KICBZaGF0IDwtIHByZWRpY3Qob2JqID0gZG1vZCwgbmV3ZGF0YSA9IGNoZWRkYXJbZHRlc3QsXSkNCiAgZXJyMSA8LSBlcnIxICsgbWVhbigoWSAtIFloYXQpXjIpDQp9DQplcnIxIDwtIGVycjEvNQ0KZXJyMSAjIEgyUyArIExBQ1RJQyB0aWVuZSBlcnJvciBtZWRpbyAxMS42Mw0KDQoNCmVycjI8LTANCmZvciAoaSBpbiA1KXsNCiAgZHRyYWluIDwtIGxpc3RhX3RyYWluW1tpXV0NCiAgZHRlc3QgPC0gbGlzdGFfdGVzdFtbaV1dDQogIGRtb2QgPC0gbG0odGFzdGUgfiBMYWN0aWMsIGRhdGEgPSBjaGVkZGFyW2R0cmFpbixdKQ0KICBZIDwtIGNoZWRkYXJbZHRlc3QsXSR0YXN0ZQ0KICBZaGF0IDwtIHByZWRpY3Qob2JqID0gZG1vZCwgbmV3ZGF0YSA9IGNoZWRkYXJbZHRlc3QsXSkNCiAgZXJyMiA8LSBlcnIyICsgbWVhbigoWSAtIFloYXQpXjIpDQp9DQplcnIyIDwtIGVycjIvNQ0KZXJyMiAjIExBQ1RJQyB0aWVuZSBlcnJvciBtZWRpbyAxOS40DQoNCmVycjEgPCBlcnIyICMgQ29uY2x1aW1vcyBxdWUgZWwgbW9kZWxvIHRhc3RlIH4gSDJTICsgTGFjdGljIGVzIG1lam9yIHF1ZSB0YXN0ZSB+IExhY3RpYy4NCg0KDQoNCg0KDQojIDYpIENvbmNsdXNpb24NCg0KbW9kZWwueSA8LSBsbSh0YXN0ZSB+IEgyUyArIExhY3RpYyxkYXRhPWNoZWRkYXIpICMgdG9tYW1vcyBlbCBtZWpvciBtb2RlbG8gZGUgbG9zIG9idGVuaWRvcyBlbiA0DQpzdW1tYXJ5KG1vZGVsLnkpDQpwbG90KG1vZGVsLnkpDQoNCiMgVmVhbW9zIGxvcyBwb3NpYmxlcyBvdXRsaWVycw0Kb3V0bGllclRlc3QobW9kZWwueSkNCmluZmx1ZW5jZVBsb3QobW9kZWwueSkNCg0KDQojIEVzdHVkaW8gZGUgaGlww7N0ZXNpcyBzdXB1ZXN0YXMNCg0Kc2hhcGlyby50ZXN0KHJlc2lkKG1vZGVsLnkpKSAjIG5vcm1hbGlkYWQgZGUgcmVzaWR1b3MNCnQudGVzdChyZXNpZChtb2RlbC55KSwgbXUgPSAwLCBhbHRlcm5hdGl2ZSA9ICJ0d28uc2lkZWQiKSAjIG1lZGlhIGNlcm8gZGUgbG9zIHJlc2lkdW9zDQpuY3ZUZXN0KG1vZGVsLnkpICMgdmFyaWFuemEgY29uc3RhbnRlIGRlIGxvcyByZXNpZHVvcw0KZHVyYmluV2F0c29uVGVzdChtb2RlbC55KSAjIG5vIGF1dG9jb3JyZWxhY2lvbg0KcmVzZXR0ZXN0KG1vZGVsLnkgLHBvd2VyPTI6MywgdHlwZT0icmVncmVzc29yIiwgZGF0YT1jaGVkZGFyKSAjIGxpbmVhbGlkYWQNCg0KIyBFZmVjdGl2YW1lbnRlLCBjdW1wbGUgdG9kYXMgbGFzIGhpcMOzdGVzaXMNCg0KDQpzdW1tYXJ5KG1vZGVsLnkpICMgZW4gZWwgc3VtbWFyeSBvYnNlcnZhbW9zIGxvcyB2YWxvcmVzIGRlIGJldGFoYXQsIHN1cyBwLXZhbG9yZXMgeSBzaWdtYQ0KDQpjb2VmZiA8LSBzdW1tYXJ5KG1vZGVsLnkpJGNvZWZmWywxXQ0KY29lZmYNCg0KIyBDYWxjdWxvIGRlIGludGVydmFsbyBkZSBjb25maWFuemEgZGUgYmV0YTEoSDJTKSB5IGJldGEyKExhY3RpYykNCg0KIyBNZXRvZG8gQm9uZmVycm9uaQ0KYWxwaGEgPC0gMC4xMA0Kc3VtbWFyeShtb2RlbC55KSRjb2VmDQpiIDwtIHN1bW1hcnkobW9kZWwueSkkY29lZlsyOjMsIDFdDQpzLmIgPC0gc3VtbWFyeShtb2RlbC55KSRjb2VmWzI6MywgMl0NCmcgPC0gMw0KbiA8LSBucm93KGNoZWRkYXIpDQpwIDwtIG5jb2woc3VtbWFyeShtb2RlbC55KSRjb2VmKQ0KdF90ZW8gPC0gcXQoMSAtIGFscGhhIC8gKDIgKiBnKSwgbiAtIHApDQpCb21TaW1DSSA8LSBtYXRyaXgoYyhiIC0gdF90ZW8gKiBzLmIsIGIgKyB0X3RlbyAqIHMuYiksIG5jb2wgPSAyKQ0KY29uZiA8LSBjKCI1JSIsICI5NSUiKQ0KYm5hbSA8LSBjKCJIMlMiLCAiTGFjdGljIikNCmRpbW5hbWVzKEJvbVNpbUNJKSA8LSBsaXN0KGJuYW0sIGNvbmYpDQpCb21TaW1DSQ0KDQojIEludGVydmFsbyBkZSBjb25maWFuemEgc2ltdWx0YW5lbyBwb3IgZWwgbWV0b2RvIGRlIFNjaGVmZmUNClEgPC0gcCAtIDENCmZfdGVvIDwtIHFmKDAuOSwgUSwgbiAtIHApIzAuOSBubyBzZXJpYSAwLjk1Pw0KU2NoU2ltQ0kgPC0gbWF0cml4KGMoYiAtIHNxcnQoUSAqIGZfdGVvKSAqIHMuYiwgYiArIHNxcnQoUSAqIGZfdGVvKSAqIHMuYiksIG5jb2wgPSAyKQ0KY29uZiA8LSBjKCI1JSIsICI5NSUiKQ0KYm5hbSA8LSBjKCJIMlMiLCAiTGFjdGljIikNCmRpbW5hbWVzKFNjaFNpbUNJKSA8LSBsaXN0KGJuYW0sIGNvbmYpDQpTY2hTaW1DSQ0KDQoNCiMgTGEgZWN1YWNpw7NuIGRlIG51ZXN0cm8gbW9kZWxvIGZpbmFsIGVzIHkgPSAoLTI3LjYpICsgMy45NSp4X0ggKyAxOS45KnhfTCwNCiMgICAgZG9uZGUgeF9IIHkgeF9MIGRlbm90YW4gbG9zIHZhbG9yZXMgb2JzZXJ2YWRvcyBkZSBIMlMgeSBMYWN0aWMuDQoNCg0KcnNlIDwtIHNxcnQoZGV2aWFuY2UobW9kZWwueSkvZGYucmVzaWR1YWwobW9kZWwueSkpDQpyc2UgICMgdmFyaWFuemEgZGUgbG9zIHJlc2lkdW9zDQoNCnB2YWwgPC0gc3VtbWFyeShtb2RlbC55KSRjb2VmZlssNF0NCnB2YWwgICMgdmVjdG9yIGNvbiBsb3MgcC12YWxvcmVzDQoNCg0KIyBDYWxjdWxvIGRlIHN1IFJeMg0KYW5vdmEobW9kZWwueSkNClNTRSA8LSBhbm92YShtb2RlbC55KVszLDJdDQpTU1QgPC0gYW5vdmEobW9kZWwueSlbMSwyXSthbm92YShtb2RlbC55KVsyLDJdK2Fub3ZhKG1vZGVsLnkpWzMsMl0NCnJzcXIgPC0gMSAtIFNTRS9TU1QNCnJzcXINCnN1bW1hcnkobW9kZWwueSkkci5zcXVhcmVkIyBlcyBsYSBtaXNtYQ0KDQojIENhbGN1bG8gZGUgc3UgUl4yIGFqdXN0YWRhDQpNU0UgPC0gU1NFL2Fub3ZhKG1vZGVsLnkpWzMsMV0NCk1TVCA8LSBTU1QvKGFub3ZhKG1vZGVsLnkpWzEsMV0rYW5vdmEobW9kZWwueSlbMiwxXSthbm92YShtb2RlbC55KVszLDFdKQ0KUmFkaiA8LTEtTVNFL01TVA0KUmFkaiAgIyBzZSBjb21wcnVlYmEgZW4gbGEgdGFibGEgc3VtbWFyeSBxdWUgZWwgdmFsb3IgZXMgY29ycmVjdG8NCg0KDQojIE9ic2VydmFtb3MgY29tbyBzZSBkaXN0cmlidXllIGxhIHZhcmlhYmxlIHRhc3RlIGVuIGZ1bmNpw7NuIGRlIEgyUyB5IExhY3RpYw0KcGxvdF9seSh4PUgyUywgeT1MYWN0aWMsIHo9dGFzdGUsIHR5cGU9InNjYXR0ZXIzZCIsIG1vZGU9Im1hcmtlciIsIGNvbG9yPXRhc3RlKSAlPiUNCiAgbGF5b3V0KHNjZW5lID0gbGlzdCh4YXhpcyA9IGxpc3QodGl0bGUgPSAnSDJTICglKScpLA0KICAgICAgICAgICAgICAgICAgICAgIHlheGlzID0gbGlzdCh0aXRsZSA9ICdMYWN0aWMgKCUpJyksDQogICAgICAgICAgICAgICAgICAgICAgemF4aXMgPSBsaXN0KHRpdGxlID0gJ1Rhc3RlICgwLTEwMCknKSkpDQoNCg0KIyBWZW1vcyBlbCBwbGFubyBkZSByZWdyZXNpb24gZGVsIG1vZGVsbyBwcm9wdWVzdG8uDQojIEVuIHJvam8gc2UgbWFyY2FuIGxhcyBvYnNlcnZhY2lvbmVzIHF1ZSBwZW9yIHNlIGFqdXN0YW4gYWwgbW9kZWxvLg0KcGxhbmVyZWcgPC0gc2NhdHRlcnBsb3QzZCh4PUgyUywgeT1MYWN0aWMsIHo9dGFzdGUsIHBjaD0xNiwgY2V4LmxhYj0xLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBoaWdobGlnaHQuM2Q9VFJVRSwgdHlwZT0iaCIsIHhsYWI9J0gyUyAoJSknLA0KICAgICAgICAgICAgICAgICAgICAgICAgICB5bGFiPSdMYWN0aWMgKCUpJywgemxhYj0nVGFzdGUgKDAtMTAwKScpDQpwbGFuZXJlZyRwbGFuZTNkKG1vZGVsLnksIGx0eS5ib3g9InNvbGlkIiwgY29sPSdtZWRpdW1ibHVlJykNCmBgYA==